在Dispatcher.BeginInvoke()中使用async / await

时间:2014-05-03 09:24:47

标签: c# wpf asynchronous lambda async-await

我有一个方法,其中包含一些执行await操作的代码:

public async Task DoSomething()
{
    var x = await ...;
}

我需要在Dispatcher线程上运行该代码。现在,Dispatcher.BeginInvoke()是等待的,但我无法将lambda标记为async,以便从内部运行await,如下所示:

public async Task DoSomething()
{
    App.Current.Dispatcher.BeginInvoke(async () =>
        {
            var x = await ...;
        }
    );
}

在内部async上,我收到错误:

  

无法将lambda表达式转换为'System.Delegate'类型,因为它不是委托类型。

如何在async内使用Dispatcher.BeginInvoke()

2 个答案:

答案 0 :(得分:46)

other answer可能引入了一个模糊的错误。这段代码:

public async Task DoSomething()
{
    App.Current.Dispatcher.Invoke(async () =>
    {
        var x = await ...;
    });
}

使用Dispatcher.Invoke覆盖形式的async void,在这种特殊情况下接受public async Task<int> DoSomethingWithUIAsync() { await Task.Delay(100); this.Title = "Hello!"; return 42; } public async Task DoSomething() { var x = await Application.Current.Dispatcher.Invoke<Task<int>>( DoSomethingWithUIAsync); Debug.Print(x.ToString()); // prints 42 } lambda。这可能会导致非常意外的行为,因为它通常发生在Dispatcher.Invoke(Action callback)

你可能正在寻找这样的东西:

Func<Task<int>>

在这种情况下,async void methods接受Task<int>参数并返回等待的DoSomethingWithUIAsync。如果您不需要从Task返回任何内容,只需使用Task<int>代替{{1}}。

或者,使用Dispatch.Invoke<Task<int>>方法之一。

答案 1 :(得分:-4)

使用Dispatcher.Invoke()

public async Task DoSomething()
{
    App.Current.Dispatcher.Invoke(async () =>
    {
        var x = await ...;
    });
}