运行 后台任务 (PCL)

Running a Task in the background (PCL)

我有一个 class 和 async 方法:

public static async Task GetData() { ... }

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

protected override void OnStart()
{
    await MyService.GetData();
}

我做不到 OnStart async. 如何在后台任务中启动它而忘记它?

I can't make OnStart Async. How do I start it in a background task and forget about it?

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

abstract class AppBase
{
    protected abstract void OnStart();
}

class App: AppBase
{
    public static async Task GetData() { await Task.Delay(1); }

    protected override async void OnStart()
    {
        await GetData(); 
    }
}

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

确保您了解 async void 方法和 Task 错误处理的一般工作方式,this material 可能会有所帮助。

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

  • 因为 GetData 已经 异步,用 Task.Run 包装它没有什么意义。它通常仅在客户端 UI 应用程序中完成,并且仅当 GetData 具有长 运行 同步部分(在它达到第一个 await 之前)。否则,您也可以在没有 Task.Run 和没有 await 的情况下调用 GetData() (这也是一个坏主意:在任何一种情况下,您都会进行一次即发即弃调用而不观察可能的异常)。

  • Task.Run 将在没有同步内容的随机池线程上启动 GetData,这对于 UI 应用或 ASP.NET应用

如果您想触发此 async 操作并忘记它,您需要做的就是调用该方法而不等待返回的任务:

protected override void OnStart()
{
    MyService.GetDataAsync();
}

但是,由于您没有观察任务,因此您永远不会知道它是否成功完成。

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

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 用作 ,但是使用 async void 会更糟糕,因为 async void 方法(不是 UI 事件处理程序)将 拆除整个过程*.

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

protected override async void OnStart()
{
    try
    {
        await GetData(); 
    }
    catch (Exception e)
    {
        // handle e.
    }
}

但我仍然建议不要这样做,因为即使完全崩溃的可能性也很危险。


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