[英]Stuck with async await thread
In constructor I want to call one method type :在构造函数中,我想调用一种方法类型:
private async Task OnLoadPrometDanKorisnikDatum
and I want to wait that method while its finish, and I have more method(3) like this and I want to call this 3 methods in background thread and don't wait him to finish, just want to wait first method.我想在该方法完成时等待该方法,并且我有更多这样的方法(3),我想在后台线程中调用这 3 个方法,不要等待他完成,只想等待第一个方法。 And I want to them executing parallel.
我希望它们并行执行。 I have methods async Task,and in constructor of view model I call like this
我有异步任务方法,并且在视图模型的构造函数中我这样调用
OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat,
DatumVrednost).Wait();
OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja).Wait();
if I don't place .Wait() on the end, program doesn't work.如果我不把 .Wait() 放在最后,程序就不起作用。 I see in debug mode they run asynchronly, but time spent tell me that they sub(one method time + second method time + ....).
我在调试模式下看到它们异步运行,但是花费的时间告诉我它们是子(一种方法时间 + 第二种方法时间 + ....)。 Can someone help me, this is for me very stuf...
有人可以帮助我吗,这对我来说非常重要...
The best way to handle your scenario is to use async void
.处理您的场景的最佳方法是使用
async void
。
I recommend first reading the Explanation
section below to fully understand the best practices around async void
.我建议首先阅读下面的
Explanation
部分,以充分了解有关async void
的最佳实践。
public MyConstructor()
{
ExecuteAsyncMethods();
}
async void ExecuteAsyncMethods()
{
try
{
await OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat, DatumVrednost);
await OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja);
}
catch(Exception e)
{
//Handle Exception
}
}
Many C# devs are taught "Never use async void
", but this is one of the few use-cases for it.许多 C# 开发人员都被教导“永远不要使用
async void
”,但这是为数不多的用例之一。
Yes async void
can be dangerous and here's why:是的
async void
可能很危险,原因如下:
await
an async avoid
methodawait
async avoid
方法Exception
thrown by async void
methodsasync void
方法抛出的Exception
try/catch
block will not catch the Exception
thrown here:try/catch
块不会捕获这里抛出的Exception
:public MyConstructor()
{
try
{
//Cannot await `async void`
AsyncVoidMethodWithException();
}
catch(Exception e)
{
//Will never catch the `Exception` thrown in `AsyncVoidMethodWithException` because `AsyncVoidMethodWithException` cannot be awaited
}
//code here will be executing by the time `AsyncVoidMethodWithException` throws the exception
}
async void AsyncVoidMethodWithException()
{
await Task.Delay(2000);
throw new Exception();
}
That being said, as long as we wrap the contents of our entire async void
in a try/catch
block, we will be able to catch the exception, like so:话虽如此,只要我们将整个
async void
的内容包装在try/catch
块中,我们就能够捕获异常,如下所示:
public MyConstructor()
{
AsyncVoidMethodWithException();
}
async void AsyncVoidMethodWithException()
{
try
{
await Task.Delay(2000);
throw new Exception();
}
catch(Exception e)
{
//Exception will be caught and successfully handled
}
}
I created a library to help with this and its additional benefit is that it avoids writing async void
code that could be potentially misused by future devs.我创建了一个库来帮助解决这个问题,它的额外好处是它避免了编写可能被未来开发人员误用的
async void
代码。
It's open source and also available on NuGet:它是开源的,也可以在 NuGet 上获得:
SafeFireAndForget
allows us to safely execute a Task
whilst not blocking the calling thread and without waiting for it to finish before moving to the next line of code. SafeFireAndForget
允许我们在不阻塞调用线程的情况下安全地执行Task
,并且在移动到下一行代码之前无需等待它完成。
Below is a simplified version of SafeFireAndForget
that you can add to your project.下面是
SafeFireAndForget
的简化版本,您可以将其添加到您的项目中。
However, I recommend copy/pasting its complete source code or adding its NuGet Package to your library to get a more robust implementation但是,我建议复制/粘贴其完整的源代码或将其NuGet 包添加到您的库中以获得更强大的实现
public static async void SafeFireAndForget<TException>(this Task task, Action<TException> onException = null, bool continueOnCapturedContext = false) where TException : Exception
{
try
{
await task.ConfigureAwait(continueOnCapturedContext);
}
catch (TException ex) when (onException != null)
{
onException(ex);
}
}
To use SafeFireAndForget
, append it to your method call like so:要使用
SafeFireAndForget
,请将其附加到您的方法调用中,如下所示:
OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat, DatumVrednost).SafeFireAndForget();
OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja).SafeFireAndForget();
To handle any Exception
thrown by that Task
, use onException
.要处理该
Task
抛出的任何Exception
,请使用onException
。 Here's an example that prints the Exception
to the Debug Console:这是将
Exception
打印到调试控制台的示例:
OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat, DatumVrednost).SafeFireAndForget(ex => Debug.WriteLine(ex));
OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja).SafeFireAndForget(ex => Debug.WriteLine(ex));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.