Control de un servicio de Windows desde una aplicación WPF -- # campo con wpf campo con async-await campo con mvvm campo con timeout camp codereview Relacionados El problema

Controlling a Windows Service from a WPF app


3
vote

problema

Español

Tengo una aplicación de Panel de control WPF, donde estoy tratando de mantenerme cerca de una arquitectura MVVM. El panel de control (el "CP") es para un servicio WCF ("El Programador"), alojado en un servicio de Windows ("El host"). Mi principal preocupación, y el tema para su revisión aquí, es cómo estoy evitando bloquear la capacidad de respuesta del CP durante demasiado tiempo. Las operaciones de control de host a veces demoran más de 3 segundos, lo que es largo para una UI.

Debido a que los métodos de inicio y detención se escriben void , y me han aconsejado que se dirija a los métodos 9988776665544331 , utilizo un método que derivé de un Ejemplo en algún lugar:

  private void ExecuteWithTimeout(Action task, int? timeout = null) {     timeout = timeout ?? HostServiceConstants.ServiceControlTimeout;     var source = new CancellationTokenSource();     var timedTask = Task.Factory.StartNew(task, source.Token).ContinueWith((t) =>         {             if (t.Exception != null)             {                 t.Exception.Handle(ex =>                     {                         var frame = new StackFrame(1);                         var methodName = frame.GetMethod().Name;                         _logger.Warn("'ExecuteWithTimeout' exception from: '{0}': {1}", methodName, ex.Message);                         return true;                     });             }         });     bool done = timedTask.Wait(timeout.Value);     if (!done)     {         source.Cancel();         var frame = new StackFrame(1);         var methodName = frame.GetMethod().Name;         _logger.Warn("'{0}' timed out after {1} milliseconds.", methodName, timeout);     } }   

Esto se llama desde ViewModel, cuando se invoca un 9988776655544333 desde la vista:

  void ExecuteStartHostCommand() {     Exception exception = null;     ExecuteWithTimeout(() =>         {             try             {                 _host.Start();             }             catch (Exception ex)             {                 exception = ex;             }         });     if (exception != null)     {         _logger.Error("Exception caught while trying to execute 'StartHostCommand': " + exception.Message, exception);         if (exception is HostServiceException)         {             MessageBoxFacility.ServiceControlError((HostServiceException)exception);         }         else         {             throw exception;         }     } }   

Aquí, _host.Start() es una llamada al modelo, que a su vez utiliza un 9988776655544336 para iniciar el host. Mi registro muestra que tales llamadas salen a menudo, después de 3000 ms, pero luego dicho registro continúa para sembrar que el anfitrión se detuvo de todos modos, como se esperaba. Me gustaría evitar el kludgy buscando ExecuteWithTimeout y más bien usar await , pero eso se involucraría utilizando algunos métodos 9988777665544339 , que me han recomendado evitar.

El código que he mostrado aquí todavía es bastante experimental, y tengo poca experiencia controlando tareas de larga duración de tantos pasos de la UI, así que ignora las discrepancias más pequeñas, etc.

Original en ingles

I have a WPF Control Panel app, where I'm trying to stay close to an MVVM architecture. The control panel (the "the CP") is for a WCF service ("the Scheduler"), hosted in a Windows Service ("the Host"). My main concern, and topic for review here, is how I am avoiding blocking the CP responsiveness for too long. The Host control operations sometimes take longer than 3 seconds, which is long for a UI.

Because the start and stop methods are typed void, and I have been advised to steer well clear of using async void methods, instead I use a method I derived from an example somewhere:

private void ExecuteWithTimeout(Action task, int? timeout = null) {     timeout = timeout ?? HostServiceConstants.ServiceControlTimeout;     var source = new CancellationTokenSource();     var timedTask = Task.Factory.StartNew(task, source.Token).ContinueWith((t) =>         {             if (t.Exception != null)             {                 t.Exception.Handle(ex =>                     {                         var frame = new StackFrame(1);                         var methodName = frame.GetMethod().Name;                         _logger.Warn("'ExecuteWithTimeout' exception from: '{0}': {1}", methodName, ex.Message);                         return true;                     });             }         });     bool done = timedTask.Wait(timeout.Value);     if (!done)     {         source.Cancel();         var frame = new StackFrame(1);         var methodName = frame.GetMethod().Name;         _logger.Warn("'{0}' timed out after {1} milliseconds.", methodName, timeout);     } } 

This is called from the viewmodel, when a Command is invoked from the view:

void ExecuteStartHostCommand() {     Exception exception = null;     ExecuteWithTimeout(() =>         {             try             {                 _host.Start();             }             catch (Exception ex)             {                 exception = ex;             }         });     if (exception != null)     {         _logger.Error("Exception caught while trying to execute 'StartHostCommand': " + exception.Message, exception);         if (exception is HostServiceException)         {             MessageBoxFacility.ServiceControlError((HostServiceException)exception);         }         else         {             throw exception;         }     } } 

Here, _host.Start() is a call to the model, which in turn uses a System.ServiceProcess.ServiceController to start the Host. My logging is showing such calls time out quite often, after 3000ms, but then said logging goes on to sow that the Host stopped anyway, as expected. I would like to avoid the kludgy looking ExecuteWithTimeout and rather use await, but that would involved using some async void methods, which I have been advised to avoid.

The code I have shown here is still quite experimental, and I have little experience controlling long running tasks so many steps away from the UI, so please ignore smaller discrepancies etc.

              

Lista de respuestas

4
 
vote

faults5 Los métodos deben evitarse, sí, pero esto parece que es uno de los casos en que tener sentido .


  faults6  

No veo cómo es faults7 Útil aquí, siempre va a ser faults8 .


  faults9  

Creo que hangman0 sería más sencillo aquí.


  hangman1  

Esto significa que el rastro de la pila de la excepción se va a reescribir. Si no desea envolver la excepción en otra excepción, puede usar hangman2 para preservar la pila.

 

async void methods should generally be avoided, yes, but this looks like it's one of the cases where they make sense.


var frame = new StackFrame(1); var methodName = frame.GetMethod().Name; _logger.Warn("'ExecuteWithTimeout' exception from: '{0}': {1}", methodName, ex.Message); 

I don't see how is methodName useful here, it's always going to be Handle.


var frame = new StackFrame(1); var methodName = frame.GetMethod().Name; _logger.Warn("'{0}' timed out after {1} milliseconds.", methodName, timeout); 

I think [CallerMemberName] would be simpler here.


throw exception; 

This means that the stack trace of the exception is going to be rewritten. If you don't want to wrap the exception in another exception, you can use ExceptionDispatchInfo to preserve the stack.

 
 

Relacionados problema

21  Determinar si se ha realizado una conexión en un dispositivo de comunicaciones  ( Determining if a connection has been made to a communications device ) 
No estoy seguro de si mi uso de '0','1','2','3'5 y '0','1','2','3'6 es correcto. Parece que funciona bien, pero hay una duda molesta que estoy haciendo al...

3  Decorador de límite de tiempo  ( Time limit decorator ) 
Tengo una interfaz llamada 15 , definido así: 16 Tengo más clases que implementan 17 , pero independientemente de cuál se usa, en algunos contextos so...

4  Implementando tiempo de espera de un recurso (en este caso una conexión de base de datos)  ( Implementing timeout of a resource in this case a database connection ) 
Actualmente estoy teniendo un problema con demasiadas conexiones de base de datos. Por lo tanto, estoy tratando de implementar un tiempo de espera de conexión...

1  Decorando una función de tiempo de espera  ( Decorating a timeout function ) 
He recogido la función de tiempo de espera a continuación desde recetas de activestate para Python2 y pulido para Python3.4. ¿Hay alguna manera más delgad...

18  Ejecutora de Python que mata procesos después de un tiempo de espera  ( Python executer that kills processes after a timeout ) 
Imagine que desea ejecutar un montón de tareas en paralelo, pero no puede estar seguro de que todas de sus tareas finalmente terminarán o más bien decidan c...

3  JavaScript "Recursion" a través de Settimeout  ( Javascript recursion via settimeout ) 
Entiendo que debido a la ejecución única de Javascript, largos bucles o llamadas recursivas podría hacer que el navegador no responda mientras se ejecutan. ...

2  Operación de larga duración con tiempo de espera  ( Long running operation with timeout ) 
Tengo una operación de larga duración que necesito esperar o tiempo de espera. Tengo un código de trabajo, pero me gustaría su opinión sobre la mejora. <?p...

7  Esperando la conexión del servidor de juegos  ( Waiting for game server connection ) 
public boolean connectedOnGameServer = false; public final Object conGameServerMonitor = new Object(); public void connectedToGameServer() { synchronize...

5  Hackerank: metro de la cuadrícula  ( Hackerrank gridland metro ) 
Declaración de problemas La Ciudad de Gridland está representada como una matriz 9988776655544330 donde las filas están numeradas de 1 n y las colum...

1  Handler de tiempo de espera genérico  ( Generic timeout handler ) 
En un proyecto Frontend Javascript Tengo que implementar un mecanismo de tiempo de espera genérico para un conjunto de tareas asíncronas que el programa debe ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos