Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在后台运行任务(PCL)_C#_.net_Task Parallel Library_Async Await_Task - Fatal编程技术网

C# 在后台运行任务(PCL)

C# 在后台运行任务(PCL),c#,.net,task-parallel-library,async-await,task,C#,.net,Task Parallel Library,Async Await,Task,我有一个使用异步方法的类: 在我使用的应用程序框架中,我需要启动该过程,并在应用程序启动时忘记它: protected override void OnStart() { await MyService.GetData(); } 我无法使OnStart异步。我如何在后台任务中启动它并忘记它 我无法使OnStart异步。如何在后台任务中启动它,以及 忘了它吧 为什么不呢?没有什么可以阻止您使其异步。async修饰符不影响CLR方法签名,即,您可以重写void方法并使其异步: 这样,如果G

我有一个使用异步方法的类:

在我使用的应用程序框架中,我需要启动该过程,并在应用程序启动时忘记它:

protected override void OnStart()
{
    await MyService.GetData();
}
我无法使OnStart异步。我如何在后台任务中启动它并忘记它

我无法使OnStart异步。如何在后台任务中启动它,以及 忘了它吧

为什么不呢?没有什么可以阻止您使其异步。async修饰符不影响CLR方法签名,即,您可以重写void方法并使其异步:

这样,如果GetData抛出,至少您会看到一个异常,这与另一个答案所建议的不同

确保您了解异步void方法和任务错误处理通常是如何工作的,这可能会有所帮助

Task.Run=>MyService.GetData的其他一些问题:

由于GetData已经是异步的,所以用Task.Run包装它没有什么意义。它通常只在客户端UI应用程序中完成,并且只有当GetData在第一次等待之前有一个长时间运行的同步部分时才能完成。否则,您最好在不使用Task.Run和Wait的情况下调用GetData,这也是一个坏主意:在任何一种情况下,您都会在不观察可能的异常的情况下执行fire and forget调用

Task.Run将在没有同步内容的随机池线程上启动GetData,这可能是UI应用程序或ASP.NET应用程序的问题

我无法使OnStart异步。如何在后台任务中启动它,以及 忘了它吧

为什么不呢?没有什么可以阻止您使其异步。async修饰符不影响CLR方法签名,即,您可以重写void方法并使其异步:

这样,如果GetData抛出,至少您会看到一个异常,这与另一个答案所建议的不同

确保您了解异步void方法和任务错误处理通常是如何工作的,这可能会有所帮助

Task.Run=>MyService.GetData的其他一些问题:

由于GetData已经是异步的,所以用Task.Run包装它没有什么意义。它通常只在客户端UI应用程序中完成,并且只有当GetData在第一次等待之前有一个长时间运行的同步部分时才能完成。否则,您最好在不使用Task.Run和Wait的情况下调用GetData,这也是一个坏主意:在任何一种情况下,您都会在不观察可能的异常的情况下执行fire and forget调用

Task.Run将在没有同步内容的随机池线程上启动GetData,这可能是UI应用程序或ASP.NET应用程序的问题

如果您想触发此异步操作并忘记它,则只需在不等待返回任务的情况下调用该方法:

protected override void OnStart()
{
    MyService.GetDataAsync();
}
然而,由于你没有观察任务,你永远不会知道它是否成功完成

您应该保留对任务的引用,并在以后等待:

public Task _dataTask;
protected override void OnStart()
{
    _dataTask = MyService.GetDataAsync();
}

public Task AwaitInitializationAsync()
{
    return _dataTask;
}
或添加处理任何异常的延续:

protected override void OnStart()
{
    MyService.GetDataAsync().ContinueWith(t => 
    {
        try 
        { 
            t.Wait();
        }
        catch (Exception e)
        {
            // handle exceptions
        }
    });
}
您不应该使用Task.Run-as,但是使用async void更糟糕,因为非UI事件处理程序的async void方法中的异常会破坏整个进程*

您可以尝试使该方法async void,同时确保不会在其中抛出任何异常,并使用try-catch块:

但我仍然建议不要这样做,因为即使是完全撞车的机会也是危险的

*您可以通过为AppDomain.CurrentDomain.UnhandledException注册偶数处理程序来解决此问题,但这应该是最后的手段,而不是最佳做法

如果您想启动此异步操作并忘记它,则只需在不等待返回任务的情况下调用该方法即可:

protected override void OnStart()
{
    MyService.GetDataAsync();
}
然而,由于你没有观察任务,你永远不会知道它是否成功完成

您应该保留对任务的引用,并在以后等待:

public Task _dataTask;
protected override void OnStart()
{
    _dataTask = MyService.GetDataAsync();
}

public Task AwaitInitializationAsync()
{
    return _dataTask;
}
或添加处理任何异常的延续:

protected override void OnStart()
{
    MyService.GetDataAsync().ContinueWith(t => 
    {
        try 
        { 
            t.Wait();
        }
        catch (Exception e)
        {
            // handle exceptions
        }
    });
}
您不应该使用Task.Run-as,但是使用async void更糟糕,因为非UI事件处理程序的async void方法中的异常会破坏整个进程*

您可以尝试使该方法async void,同时确保不会在其中抛出任何异常,并使用try-catch块:

但我仍然建议不要这样做,因为即使是完全撞车的机会也是危险的


*您可以通过为AppDomain.CurrentDomain.UnhandledException注册一个偶数处理程序来解决这个问题,但这应该是最后的手段,而不是最佳做法

我认为这是一个坏主意,为什么在您不在乎它何时完成的情况下等待它呢?只要调用该方法并忽略该任务。@l3arnon,我的回答中有一个链接,详细介绍了异步void方法的工作原理,包括异常。OP是否想处理这里的异常,请参见Eric Lippert的,或者他是否想使流程崩溃,这取决于他。关键是这些异常不会被忽视。@Servy,请参阅我上面的评论

. 有关更详细的讨论,请参阅。最不理想的行为实际上是忽略异常,而最上面的行为是破坏整个过程。有很多方法可以避免忽略例外情况:2个事件,尝试捕捉内部,继续和崩溃是最不愉快和最危险的。我认为这是一个坏主意,为什么在你不在乎它何时结束的时候等待它?只要调用该方法并忽略该任务。@l3arnon,我的回答中有一个链接,详细介绍了异步void方法的工作原理,包括异常。OP是否想处理这里的异常,请参见Eric Lippert的,或者他是否想使流程崩溃,这取决于他。关键是这些异常不会被忽视。@Servy,请参阅我上面的评论。有关更详细的讨论,请参阅。最不理想的行为实际上是忽略异常,而最上面的行为是破坏整个过程。有很多方法可以避免忽略异常:2个事件,try-catch-inside,continuations和crashing是最不愉快和最危险的。OP是想处理异常,还是破坏流程,取决于他,请参阅我答案的注释。最不可取的行为是忽略fire的异常并忘记任务,这是我的观点。也就是说,如果他确实想处理它们,为什么要使用ContinueWith而不是async void with wait inside try/catch inside?很高兴看到您进行了编辑。我几乎想不出有哪种用例ContinueWith比async/await有任何优势,或者不能被async/await替代。特别是,请记住在continuations中错误处理的含义。当然,我对async Wait没有问题,但async void是用于UI事件处理程序的,通常在其他地方不鼓励使用。我想说的是,不仅是UI事件处理程序,还有任何类型的事件处理程序。就我个人而言,我不认为这是一个教条。我还将其用于类似On的可覆盖通知,如OP的OnStart,以及前面讨论的fire and forget任务。OP是否要处理异常或中断流程,取决于他,请参阅我答案的注释。最不可取的行为是忽略fire的异常并忘记任务,这是我的观点。也就是说,如果他确实想处理它们,为什么要使用ContinueWith而不是async void with wait inside try/catch inside?很高兴看到您进行了编辑。我几乎想不出有哪种用例ContinueWith比async/await有任何优势,或者不能被async/await替代。特别是,请记住在continuations中错误处理的含义。当然,我对async Wait没有问题,但async void是用于UI事件处理程序的,通常在其他地方不鼓励使用。我想说的是,不仅是UI事件处理程序,还有任何类型的事件处理程序。就我个人而言,我不认为这是一个教条。我还将其用于类似On的可覆盖通知,如OP的OnStart,以及前面讨论的fire和forget任务。任务在后台线程上运行。你在问什么?GetData在启动异步部分之前是否进行了大量同步处理?任务在后台线程上运行。你在问什么?GetData在启动异步部分之前是否进行了大量的同步处理?