Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用带有结果的异步版本实现函数_C#_Async Await - Fatal编程技术网

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);
} 

您可能想阅读的两篇文章-和。这两篇文章的答案通常都是否定的。