我有一个async
方法的课程:
public static async Task GetData() { ... }
在我使用的应用程序框架中,我需要启动该过程并在应用程序启动时忘记它:
protected override void OnStart()
{
await MyService.GetData();
}
我无法OnStart
async.
如何在后台任务中启动它并忘掉它?
答案 0 :(得分:4)
我无法制作OnStart Async。如何在后台任务中启动它 忘了吗?
为什么不呢?没有什么能阻止你做出async
。 async
修饰符不会影响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
之前)。否则,您也可以在没有GetData()
且没有Task.Run
的情况下致电await
(这也是一个不好的主意:在任何一种情况下,您都会做一场大火 - 而且 - 忘记调用而不遵守可能的例外情况。)
Task.Run
将在没有同步内容的随机池线程上启动GetData
,这可能是UI应用程序或ASP.NET应用程序的问题。
答案 1 :(得分:1)
如果要触发此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
用作Noseratio explained,但使用async void
会更加糟糕,因为async void
方法中的例外情况(不是{39}} UI事件处理程序)将拆除整个过程* 。
您可以尝试制作方法async void
,同时确保使用try-catch
块不会引发任何异常:
protected override async void OnStart()
{
try
{
await GetData();
}
catch (Exception e)
{
// handle e.
}
}
但我仍然建议反对它,因为即使完全崩溃的可能性也很危险。
*您可以通过为AppDomain.CurrentDomain.UnhandledException
注册一个偶数处理程序来解决这个问题,但这应该是最后的选择,而不是最佳实践