C#等任务,而不阻塞UI
让我们先从代码: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。我该如何解决这个问题?
如果可以,您应该移动到新的async/await
关键字和周围的支持。
对于你的问题的特定代码,这里就是我会做:
- 标记方法
async Task
要清楚调用代码,这种方法是异步 - 使用
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);
}
}
这很好用!我怎样才能给它一个变量名? 'var task = await ...'不起作用?我想转发一个取消标记 – Norgul
要转发取消标记,必须将其作为参数的一部分发送,如果任务返回某些内容,即。它被定义为'任务
我知道,但为了做到这一点,我需要将任务注册为变量,以了解它是否正在运行?我试着用'var task = new Task(()=> ..'),但是如果我做'等待任务',它不会启动。 '等待task.Start()'抛出错误...编辑...明白了,nvm,谢谢:) – Norgul
如果您不阻止用户界面,您是否认为您可能能够在其执行过程中再次启动该操作?我的意思是,如果在按钮上调用了“StartStopService”,是否考虑过在这种情况发生时是否需要禁用按钮? –
现在在异步/等待世界中的正常方式是将你的方法标记为“async Task”(而不是'void'),并使用'await task;'等待任务完成。请注意我之前对不阻止用户界面的评论。 –
那么最终的想法是转发按钮点击取消令牌如果任务仍在执行 – Norgul