我可以使用async / await来模拟后台工作者吗?

时间:2015-04-09 15:29:31

标签: c# .net multithreading async-await task-parallel-library

我正在努力避免将一堆BackgroundWorkers链接在一起。我正在做一些事情,要求我在继续执行之前等待UI更新。显然,我不能使用Sleep,因为这会阻止UI线程更新并破坏目的。我发现下面的代码我认为是答案,但似乎task.Wait();行仍然阻止了UI线程。

static void Main(string[] args)
{
    var task = Task.Run(() => DoSomething());
    task.Wait();
    // once the task completes, now do more
}

static void DoSomething()
{
    // something here that is looking for the UI to change
}

我也尝试了以下内容,它做了同样的事情:

static void Main(string[] args)
{
    var task = Task.Run(() => DoSomethingAsync());
    task.Wait();
    // once the task completes, now do more
}

private async Task DoSomethingAsync()
{
    // something here that is looking for the UI to change
}

是否有可能做我想做的事情,如果是的话,我做错了什么?

1 个答案:

答案 0 :(得分:6)

您需要await任务而不是阻止它。您可以在async方法中执行此操作。

现在,Main不能是async,但事件处理程序可以是(我猜你实际使用的是代码):

public async void EventHandler(object sender, EventArgs e)
{
    await Task.Run(() => DoSomething()); // wait asynchronously
    // continue on the UI thread
}

请注意,async void只能用于事件处理程序。所有其他async方法都应该返回一个任务。

使用Task.Run表示您使用的是ThreadPool线程。要真正等待UI以“执行某些操作”,您应该使用TaskCompletionSource。您创建它并await它的Task属性,并在UI更改时完成该任务:

public async void EventHandler(object sender, EventArgs e)
{
    _tcs = new TaskCompletionSource<bool>();
    await _tcs.Task;
}

public void UIChanged(object sender, EventArgs e)
{
    _tcs.SetResult(false);
}