C# 使用异步/等待的最佳实践
假设我有以下类定义:C# 使用异步/等待的最佳实践,c#,async-await,C#,Async Await,假设我有以下类定义: public class Calculator { public CalculatorResult Calculate() { return LongRunningCalculation(); } private CalculatorResult LongRunningCalculation() { return new CalculatorResult(0.00); } } public
public class Calculator
{
public CalculatorResult Calculate()
{
return LongRunningCalculation();
}
private CalculatorResult LongRunningCalculation()
{
return new CalculatorResult(0.00);
}
}
public class ClassThatUsesACalculator
{
private readonly Calculator calculator;
public ClassThatUsesACalculator()
{
this.calculator = new Calculator();
}
public void DoWork()
{
for (int i = 0; i < 10; i++)
{
var result = calculator.Calculate();
DoSomethingWithCalculationResult(result);
DoLightWork();
OnProgressChanged();
}
}
}
public partial class Form : Form
{
public Form()
{
InitializeComponent();
}
private void Method(object sender, EventArgs e)
{
DoWork();
}
private void DoWork()
{
var calculator = new ClassThatUsesACalculator();
calculator.ProgressChanged += (s, e) =>
{
// Update progressbar
};
calculator.DoWork();
}
}
如果我拥有这个库,我想还有两个选择,其中一个非常像第一个。可能是因为我自己不了解
在使用计算器的类上创建一个方法,该方法封装DoWork()
方法,然后从窗体上的异步方法调用该方法
或者
使用Task.Run()
封装Calculator
类上的LongRunningCalculation()
在表单上创建异步方法(MethodThree
)
private async void method三(对象发送方,事件参数e)
{
IProgress progress=新进度(UpdateProgressBar);
var calculator=使用计算器()的新类;
calculator.ProgressChanged+=(s,args)=>
{
进度报告(新计算器进度(0));
};
等待计算器。DoWorkAsync();
}
现在,在我看来,最后一个选择将是最好的,因为我将保持更多的控制权。但是,也许我离此很远,希望有人对此发表意见或指点,因为我只能找到关于如何使用异步的解释,而不能找到真正的方法来为其他人使用。一般来说,推送任何任务。尽可能在调用堆栈上运行用法
您想要避免的是使用Task.Run
在可重用组件中实现具有异步签名的方法。那是个骗人的API。我有一个更详细的计划
如果您控制有问题的类,我建议使用IProgress
而不是事件进行进度更新IProgress
可以很好地处理同步代码和异步代码:
public void DoWork(IProgress<CalculatorProgress> progress = null)
{
for (int i = 0; i < 10; i++)
{
var result = calculator.Calculate();
DoSomethingWithCalculationResult(result);
DoLightWork();
if (progress != null)
progress.Report(new CalculatorProgress(...));
}
}
public void DoWork(IProgress progress=null)
{
对于(int i=0;i<10;i++)
{
var result=calculator.Calculate();
计算结果(结果)的dosomething;
DoLightWork();
如果(进度!=null)
进度报告(新计算器程序(…);
}
}
那么使用它是非常简单的:
private async void MethodTwo(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress>(UpdateProgressBar);
var calculator = new ClassThatUsesACalculator();
await Task.Run(() => calculator.DoWork(progress));
}
private async void method2(对象发送方,事件参数e)
{
IProgress progress=新进度(UpdateProgressBar);
var calculator=使用计算器()的新类;
等待任务。运行(()=>calculator.DoWork(progress));
}
这就保留了任务。在需要它的组件(UI层)中运行用法,并将其排除在业务逻辑之外。您的问题非常长,而且过于冗长。如果您将问题缩小到简要地解释您想知道的内容,可能会有所帮助。顺便说一句,对于快速的东西,async
实际上并不是必需的<代码>异步
对于访问文件、数据库或web服务等I/O任务非常有用。但是运行快速非I/O代码的开销实际上可能会降低性能。这应该在山顶上演唱。
public async Task DoWorkAsync()
{
for (int i = 0; i < 10; i++)
{
var result = await calculator.CalculateAsync();
DoSomethingWithCalculationResult(result);
DoLightWork();
OnProgressChanged();
}
}
private async void MethodThree(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress>(UpdateProgressBar);
var calculator = new ClassThatUsesACalculator();
calculator.ProgressChanged += (s, args) =>
{
progress.Report(new CalculatorProgress(0));
};
await calculator.DoWorkAsync();
}
public void DoWork(IProgress<CalculatorProgress> progress = null)
{
for (int i = 0; i < 10; i++)
{
var result = calculator.Calculate();
DoSomethingWithCalculationResult(result);
DoLightWork();
if (progress != null)
progress.Report(new CalculatorProgress(...));
}
}
private async void MethodTwo(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress>(UpdateProgressBar);
var calculator = new ClassThatUsesACalculator();
await Task.Run(() => calculator.DoWork(progress));
}