C# 在void函数中使用Task.Run是错误的还是错误的做法?

C# 在void函数中使用Task.Run是错误的还是错误的做法?,c#,concurrency,task,C#,Concurrency,Task,我试图创建一种类型的fire and forget函数,在这种函数中,我不关心函数的完成或结果。为了做到这一点,我在该函数体中使用Task.Run,这样我就可以并发运行它并立即从中返回 我认为重要的一点是,它运行的是一个IIS应用程序 大概是这样的: void ReallyImportantFunction() { //Do really important work NotSoImportantWork("some data"); //Do really imp

我试图创建一种类型的fire and forget函数,在这种函数中,我不关心函数的完成或结果。为了做到这一点,我在该函数体中使用Task.Run,这样我就可以并发运行它并立即从中返回

我认为重要的一点是,它运行的是一个IIS应用程序

大概是这样的:

void ReallyImportantFunction()
{
    //Do really important work
        NotSoImportantWork("some data");
    //Do really important work

}

void NotSoImportantWork(string data)
{
    Task.Run(() =>
    {
        try
        {
            //Do something here with the data   
        }
        catch (Exception ex)
        {
            //Log exception do not throw

        }


    });
}

如果没有更多的信息,很难回答这个问题,但我认为您误解了Task.Run和异步代码的用法。如果这是一项不重要的工作,并且您不关心结果或它的完成情况,那么您可能会问是否需要首先在这里运行它。其次,Task.Run通常用于执行可能阻塞UI线程的长时间运行的代码。如果您正在进行DB调用或写入文件系统,将此逻辑放入任务中可能是有意义的。例如

void ReallyImportantFunction()
{
    try
    {
        //Do really important work
        Task.Run(() => NotSoImportantWork("some data"));
        //Do really important work

    }
    catch (Exception ex)
    {
        / Handle the exception
    }
}

void NotSoImportantWork(string data)
{
    //Do something here with the data   
}
然而,如果你真的使用过你正在计算的任何东西,或者如果你的计算有任何副作用或变异,这会让你面临数据竞争。如果你说的是真的,而你从来都不去看结果,我可能会问,为什么它会出现在一开始的方法中。如果你不打算用那些重要的东西,为什么不在重要的中间呢?如果您正在使用结果,或者正在修改所需的内容,那么代码正确地等待结果是有意义的

async void ReallyImportantFunction()
{
    try
    {
        //Do really important work
        var myResult = await IOIntensiveWork("some data");
        //Do really important work
    }
    catch (Exception ex)
    {
        // Handle the exception
    }
}

Task<MyResult> IOIntensiveWork(string data)
{
    //Do something here with the data   
}
如果您也可以避免异步void方法,那么它通常会更干净,尽管它没有什么必然的错误。只要记住总是检查例外情况

编辑:根据你在评论中写的内容,我认为将你不重要的工作包装在任务中是有意义的。这并不是因为它不重要,而是因为您显然正在进行网络呼叫,并且在与您无法控制的服务通信时可能会出现各种问题

所以您可以只运行Task.Run=>NotSoImportantWork。。。;来自ReallyImportantFunction,但要注意捕捉异常的位置,以及如果出现异常,代码可能会退出的位置。我可能更喜欢启动任务。在那里运行,而不是在NotSoImportantWork中运行,因为您可能会使用Task.Run…ConfigureWaitFalse;要从代码中挤出最后一点性能,这在很大程度上取决于代码的结构

根据您从何处启动任务,您可以使用…ConfigureWaitFalse;也就是说,当操作完成时,您不需要将任务返回到当前上下文。这有时可以提高性能。只要有意义,就尝试使用它。有关更多信息,请查看以下内容:


如果代码没有更多的上下文,就很难深入到比这更详细的内容。希望有帮助

任务!=线程。删除了多线程标记。NotSoImportantWork是对托管在另一台机器上的message broker的网络调用,该机器记录有关已处理数据的一些信息。每次新的数据包出现时,这些信息都会更新,所以如果出现问题,我真的不在乎,因为下一个数据包无论如何都会更新它。还有几点。ReallyImportantFunction的性能对我们的业务至关重要,因此尽可能将其执行时间增加到0毫秒是理想的。NotSoImportantWork是从多个地方调用的,这就是我添加任务的原因。运行到它的主体,而不是在外部复制。我刚刚编辑了我的答案,以包含一些建议。看一看,告诉我你的想法。希望有帮助!