C# 使用带有结果的异步版本实现函数
我正在实现函数的异步版本和普通版本。我已经实现了异步版本。对于普通版本,我可以复制粘贴,并用普通计数器部分替换异步函数调用的用法。或者我可以调用异步版本,结果如下所示 第一种方法:C# 使用带有结果的异步版本实现函数,c#,async-await,C#,Async Await,我正在实现函数的异步版本和普通版本。我已经实现了异步版本。对于普通版本,我可以复制粘贴,并用普通计数器部分替换异步函数调用的用法。或者我可以调用异步版本,结果如下所示 第一种方法: public int SomeTask(int param) { //Something going on return SomeOtherTask(); } public async Task<int> SomeTaskAsync(int param) { //Somethin
public int SomeTask(int param)
{
//Something going on
return SomeOtherTask();
}
public async Task<int> SomeTaskAsync(int param)
{
//Something going on (copy pasted)
return await SomeOtherTaskAsync();
}
public int SomeTask(int param)
{
return SomeTaskAsync(param).Result;
}
public async Task<int> SomeTaskAsync(int param)
{
//some function calls with await
}
public int-SomeTask(int-param)
{
//发生了什么事
返回SomeOtherTask();
}
公共异步任务SomeTaskAsync(int参数)
{
//正在发生的事情(复制粘贴)
return wait someothertasksync();
}
第二种方法:
public int SomeTask(int param)
{
//Something going on
return SomeOtherTask();
}
public async Task<int> SomeTaskAsync(int param)
{
//Something going on (copy pasted)
return await SomeOtherTaskAsync();
}
public int SomeTask(int param)
{
return SomeTaskAsync(param).Result;
}
public async Task<int> SomeTaskAsync(int param)
{
//some function calls with await
}
public int-SomeTask(int-param)
{
返回SomeTaskAsync(param).Result;
}
公共异步任务SomeTaskAsync(int参数)
{
//一些带有wait的函数调用
}
第二种方法是否可能存在问题?性能将受到影响。有多少是不可能知道的-您是掌握代码的人,您可以为您的确切用例进行分析 但是,创建只调用
Result
的同步版本的方法是没有意义的-方法的用户可以做同样的事情。问题是,无论如何这样做都是非常危险的,特别是当涉及到同步上下文时。考虑样本代码:
async void btnTest_Click(object sender, EventArgs e)
{
await DoSomethingAsync();
}
async Task DoSomethingAsync()
{
await Task.Delay(1000);
}
这个很好用。现在,让我们试试您的“同步”版本:
哎呀,你遇到了僵局。UI线程正在等待DoSomethingAsync
完成,但DoSomethingAsync
需要在UI线程上完成执行。如果同步等待async
方法,则永远不能假定该方法将运行
另外,通过使用
Result
而不是await
,您将失去许多异常处理功能。例如,异常堆栈跟踪将变得一团糟,您需要处理由创建任务的方法和结果
调用本身引发的异常-第一个将引发异常,直到实际必须等待的第一个等待
,第二个用于所有继续。你永远不知道哪个是哪个。首先,如果你有一个自然的异步操作,你应该公开一个异步API。正如达米恩指出的那样,答案是“不”
这类包装的一个问题是,在所有场景中都没有可用的模式!我在上一篇文章中描述了各种异步同步技术。它们都有缺点;正如Luaan所指出的,拦截黑客有可能出现死锁
但是,如果您有很好的理由这样做(即,您的库历史上有过同步方法,并且您正在添加异步方法,但希望保持同步方法向后兼容,至少在一两个版本中),那么您可以使用我的文章中描述的“布尔标记hack”
斯蒂芬·图布不久前给我看了这个把戏。其思想是,(私有)实现函数采用boolsync
参数,如果该参数为true
,则它返回的任务保证已经完成。这避免了常规阻塞的死锁问题:
private async Task<int> SomeTaskAsync(int param, bool sync)
{
// Every `await` in your code needs to honor `sync`
if (sync)
return SomeOtherTask();
else
return await SomeOtherTaskAsync();
}
public int SomeTask(int param)
{
return SomeTaskAsync(param, sync: true).GetAwaiter().GetResult();
}
public Task<int> SomeTaskAsync(int param)
{
return SomeTaskAsync(param, sync: false);
}
private async Task sometasksync(int-param,bool-sync)
{
//代码中的每个'wait'都需要遵守'sync'`
如果(同步)
返回SomeOtherTask();
其他的
return wait someothertasksync();
}
公共int SomeTask(int参数)
{
返回SomeTaskAsync(param,sync:true).GetAwaiter().GetResult();
}
公共任务SomeTaskAsync(int参数)
{
返回SomeTaskAsync(参数,sync:false);
}
您可能想阅读的两篇文章-和。这两篇文章的答案通常都是否定的。