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

时间:2019-07-16 14:54:05

标签: c# concurrency task

我正在尝试创建一种类型的“即发即弃”功能,而我并不关心该功能的完成或结果。为此,我在该函数的主体中使用了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

        }


    });
}

1 个答案:

答案 0 :(得分:1)

在没有更多信息的情况下很难回答这个问题,但是我认为您误解了Task.Run()和异步代码的使用。如果它是无关紧要的工作,并且您不关心结果或完成情况,则可能会首先询问是否需要在此处运行它。其次,Task.Run()通常用于执行长时间运行的代码,否则可能会阻塞UI线程。如果您要进行数据库调用或写入文件系统,则可以将此逻辑放入“任务”。一个例子是

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   
}

但是,如果您实际使用 ever 来使用数据,或者您的计算 ever 有任何副作用或变异,这就会使您面临数据竞争。如果您说的是正确的,但您从未看过结果,那么我可能会问为什么它是方法的开始。如果您永远不会使用重要的事物,为什么还要在它们之间计算真正不重要的事物呢?如果您正在使用结果或对所需内容进行突变,则代码可以正确等待结果。

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   
}

如果您也可以避免使用async void方法,通常会比较干净,尽管这不一定有问题。只记得要始终检查异常。

编辑:根据您在评论中所写内容,我认为将NotSoImportantWork()包装在任务中是有意义的。这并不是因为它不重要,而是因为您显然正在进行网络呼叫,并且在与您控制范围之外的服务进行通信时可能会发生各种问题。

因此,您可以只从Task.Run(() => NotSoImportantWork("..."));ReallyImportantFunction(),但是要注意在哪里捕获异常以及如果应该发生代码,代码可能在哪里退出。我可能更愿意在此处而不是在Task.Run()中启动NotSoImportantWork(),因为您可能会使用Task.Run(...).ConfigureAwait(false);从代码中挤出最后的性能(这在很大程度上取决于您的代码代码结构化。)

根据要从何处启动任务,可以使用...ConfigureAwait(false);来表示操作完成后不需要返回当前上下文。有时可以提高性能。只要有意义,请尝试并使用它。有关更多信息,请查看以下内容:When correctly use Task.Run and when just async-await

在代码中没有更多上下文的情况下,很难比这更详细。希望对您有帮助!