C# 在WPF调度程序调用中等待

C# 在WPF调度程序调用中等待,c#,wpf,async-await,C#,Wpf,Async Await,当在发送给调度程序的委托中醒来时,确保错误处理的最佳解决方案是什么 简而言之:我需要在将计算解析为Foo后返回一个数字。该计算非常缓慢,必须在UI线程上完成。计算必须作为任务交给另一个类 我能想出的唯一解决办法是打电话给FooWithAtask____;3,但我甚至不确定 public class Foo { public void CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(Task<string> task) { } }

当在发送给调度程序的委托中醒来时,确保错误处理的最佳解决方案是什么

简而言之:我需要在将计算解析为Foo后返回一个数字。该计算非常缓慢,必须在UI线程上完成。计算必须作为
任务
交给另一个类

我能想出的唯一解决办法是打电话给FooWithAtask____;3,但我甚至不确定

public class Foo
{
    public void CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(Task<string> task) { }
}

// CallFooWithATask___ is invoked from unknown thread. Can't wait for GetWithSideEffects on calling thread
public class SomeClass
{
    private TextBox textBox;

    public int CallFooWithATask___1(Foo foo)
    {
        // not good - async void -> no error handling
        var tcs = new TaskCompletionSource<string>();
        Dispatcher.CurrentDispatcher.BeginInvoke(async () =>
        {                
            var a = await GetWithSideEffects();
            textBox.Text = a;
            tcs.SetResult(a);
        });

        // quite fast - probally put it in a queue and returns
        foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(tcs.Task);

        return 1;
    }

    public async Task<int> CallFooWithATask___2(Foo foo)
    {
        // not good - still async void  -> no error handling .. when is foo actually called? I assume when hitting the inner await'ish?
        var task =  await Dispatcher.CurrentDispatcher.InvokeAsync(async () =>
        {
            var a = await GetWithSideEffects();
            textBox.Text = a;
            return a;
        });

        // quite fast - probally put it in a queue and returns
        foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(task);

        return 1;
    }

    public int CallFooWithATask___3(Foo foo)
    {
        // what is the elegant solution - probally not this?
        var tcs = new TaskCompletionSource<string>();
        Dispatcher.CurrentDispatcher.BeginInvoke(async () =>
        {
            try
            {
                var a = await GetWithSideEffects();
                textBox.Text = a;
                tcs.SetResult(a);
            }
            catch (Exception ex) { tcs.SetException(ex); }
        });

        // quite fast - probally put it in a queue and returns
        foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(tcs.Task);

        return 1;
    }

    // this might trigger ui updates and is very slow ..
    private Task<string> GetWithSideEffects()=> Task.FromResult("42");
}
公共类Foo
{
更新UIS(任务){}时完成的任务的公共void调用MEWITH
}
//从未知线程调用CallFooWithATask__;。无法在调用线程上等待GetWithSideEffects
公共类
{
私人文本框文本框;
公共int呼叫Fooowithatask___;1(Foo-Foo)
{
//不好-异步无效->无错误处理
var tcs=new TaskCompletionSource();
Dispatcher.CurrentDispatcher.BeginInvoke(异步()=>
{                
var a=等待GetWithSideEffects();
Text=a;
tcs.SetResult(a);
});
//相当快-很可能将其放入队列并返回
更新UI时已完成的任务(tcs.Task)的foo.callMeWith;
返回1;
}
公共异步任务调用FooWithAtask__2(Foo-Foo)
{
//不好-仍然异步void->no error handling..foo实际上是什么时候调用的?我假设是在命中内部wait'ish时?
var task=await Dispatcher.CurrentDispatcher.InvokeAsync(异步()=>
{
var a=等待GetWithSideEffects();
Text=a;
返回a;
});
//相当快-很可能将其放入队列并返回
foo.callmewith任务,该任务在UI更新时完成(任务);
返回1;
}
公共int呼叫Fooowithatask___;3(Foo-Foo)
{
//优雅的解决方案是什么?可能不是这个?
var tcs=new TaskCompletionSource();
Dispatcher.CurrentDispatcher.BeginInvoke(异步()=>
{
尝试
{
var a=等待GetWithSideEffects();
Text=a;
tcs.SetResult(a);
}
catch(Exception ex){tcs.SetException(ex);}
});
//相当快-很可能将其放入队列并返回
更新UI时已完成的任务(tcs.Task)的foo.callMeWith;
返回1;
}
//这可能会触发ui更新,速度非常慢。。
私有任务GetWithSideEffects()=>Task.FromResult(“42”);
}

你很接近了。只需在方法或
Func
中提取异步代码,以避免以
async void
结尾:

Func<Task<string>> func = async () =>
{
    var a = await GetWithSideEffects();

    return a;
};

您的问题是什么?当在传递给调度程序的委托中醒来时,确保错误处理的最佳解决方案是什么。通常,我建议对代码进行结构化,以便UI调用逻辑,而不是调用UI的逻辑。UI不应该向逻辑提供服务。如果逻辑需要一个服务,那么为它定义一个接口,然后UI可以实现该接口,如果绝对必要,可以使用
SynchronizationContext
var task = Dispatcher.InvokeAsync(func).Task.Unwrap();

foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(task);