2016-12-06 105 views
0

让我们先从代码:C#等任务,而不阻塞UI

private void StartStopService() 
{ 
    var task = Task.Run(() => debugService.Iterate()); 
    StartStopInit(true); 

    //task.Wait(); 
    if (task.IsCompleted) 
     StartStopInit(false); 
} 

我试图做一个计划,将通过一个同时不阻塞UI线程中执行的给定的DLL的从DB一个列表。提供的方法在按钮单击时运行,它正在启动一个任务来遍历DLL。

public void Iterate() 
{ 
    foreach (var plugin in runningPlugins) 
     ExecutePlugin(plugin); 
} 

Execute方法只是一个一个执行DLL。

我需要一个解决方案,在所有DLL完成执行后运行StartStopInit()方法。如果我把task.Wait()我会阻止UI ...情况,因为它现在当然不会工作,因为如果任务启动时条件通过。如果我执行某种无限循环来监听更改,我将再次阻止UI。我该如何解决这个问题?

+0

如果您不阻止用户界面,您是否认为您可能能够在其执行过程中再次启动该操作?我的意思是,如果在按钮上调用了“StartStopService”,是否考虑过在这种情况发生时是否需要禁用按钮? –

+2

现在在异步/等待世界中的正常方式是将你的方法标记为“async Task”(而不是'void'),并使用'await task;'等待任务完成。请注意我之前对不阻止用户界面的评论。 –

+0

那么最终的想法是转发按钮点击取消令牌如果任务仍在执行 – Norgul

回答

4

如果可以,您应该移动到新的async/await关键字和周围的支持。

对于你的问题的特定代码,这里就是我会做:

  1. 标记方法async Task要清楚调用代码,这种方法是异步
  2. 使用await在里面的任务该方法停止执行,并“等待”的任务继续

具体来说之前完成,这是它会是什么样子:

private async Task StartStopService() 
{ 
    StartStopInit(true); 
    await Task.Run(debugService.Iterate); 
    StartStopInit(false); 
} 

时序方面我会告诉周围的代码,该方法现在正在执行产卵子任务之前执行。

也考虑添加try/catch块,如果子任务抛出异常会发生什么?

private async Task StartStopService() 
{ 
    try 
    { 
     StartStopInit(true); 
     await Task.Run(debugService.Iterate); 
    } 
    catch (InvalidOperationException ex) 
    { 
     // What to do here??? 
    } 
    finally 
    { 
     StartStopInit(false); 
    } 
} 
+0

这很好用!我怎样才能给它一个变量名? 'var task = await ...'不起作用?我想转发一个取消标记 – Norgul

+0

要转发取消标记,必须将其作为参数的一部分发送,如果任务返回某些内容,即。它被定义为'任务'其中'T'是某种类型,那么你可以使用'var result = await task'来等待任务并获得结果,但是如果它只是'Task',那么你只能等待它完成。但是,再次,必须将取消标记作为参数提供给该方法。 –

+0

我知道,但为了做到这一点,我需要将任务注册为变量,以了解它是否正在运行?我试着用'var task = new Task(()=> ..'),但是如果我做'等待任务',它不会启动。 '等待task.Start()'抛出错误...编辑...明白了,nvm,谢谢:) – Norgul