简体   繁体   English

Task.Run()不会引发异常?

[英]Task.Run() doesn't raise exception?

I have the following code in the 我在下面的代码中

private void Button_Click(object sender, EventArgs e)
{
    try
    {
        Task.Run(async () => await Presenter.Search());
    }
    catch (Exception ex)
    {
        LabelMessage.Text = "Error:....";
    }
}

The function Presenter.Search() may get exceptions in some cases and I want to show an error message. 在某些情况下, Presenter.Search()函数可能会出现异常,我想显示一条错误消息。 However, the exception is not raised? 但是,异常不是引发吗? I can only see it in the Visual studio debugger. 我只能在Visual Studio调试器中看到它。

Really this should be written like so: 确实应该这样写:

private async void Button_Click(object sender, EventArgs e)
{
    try
    {
        await Presenter.Search();
    }
    catch (Exception ex)
    {
        LabelMessage.Text = "Error:....";
    }
}

Now the call is awaited and the exception will be handled correctly. 现在等待呼叫,并且可以正确处理异常。 Note that you shouldn't typically use async void for the reasons listed here , but in the case of UI event handlers it's the recommended approach. 请注意,出于此处列出的原因,通常不应该使用async void ,但是对于UI事件处理程序,则建议使用这种方法。

First of all, if Presenter.Search already returns a Task you should consider to make the event handler async and simply put 首先,如果Presenter.Search已经返回了Task ,则应考虑使事件处理程序async并简单地放置

await Presenter.Search();

in the try-catch block. 在try-catch块中。

The reason of Task.Run(Func<Task>) overload exists is that you can force an already existing Task to be scheduled for execution on a pool thread. 存在Task.Run(Func<Task>)重载的原因是,您可以强制调度已经存在的Task以在池线程上执行。 This case can be justified in very rare cases as normally you should rely on the internal implementation of the Task returning methods. 这种情况在极少数情况下是合理的,因为通常您应该依靠Task返回方法的内部实现。 But if you know that an async method does not use threads (for example, just returns a Task , which will be completed on a specific event) and you are confident enough about forcing the execution on a pool thread you can do it this way. 但是,如果您知道异步方法不使用线程(例如,仅返回Task ,它将在特定事件上完成),并且您对在池线程上强制执行有足够的信心,则可以采用这种方式。 But also in this case you should await the external task; 但是,在这种情况下,您还应该等待外部任务。 otherwise, the call is fire-and-forget and you will not catch anything: 否则,通话即被抛弃,您将一无所获:

await Task.Run(() => Presenter.Search());

Please note that I omitted the inner async-await: 请注意,我省略了内部的async-await:

await Task.Run(async () => await Presenter.Search());

This would also work and is functionally equivalent to the previous version but adds a needless inner state machine to the chain of tasks to execute. 这也将起作用,并且在功能上等效于先前版本,但是在执行的任务链中增加了不必要的内部状态机。

TL;DR: Without knowing any further details await Presenter.Search(); TL; DR:在不知道任何更多详细信息的情况下await Presenter.Search(); seems to be the better solution but also await Task.Run(() => Presenter.Search()); 似乎是更好的解决方案,但也要await Task.Run(() => Presenter.Search()); can be justified if you know what you are doing. 如果您知道自己在做什么,就可以证明是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM