Nói rằng tôi có các định nghĩa lớp sau đây:thực hành tốt nhất về việc sử dụng async/chờ đợi
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();
}
}
Nếu tôi muốn làm công việc thực hiện trong DoWork()
, về hình thức, không đồng bộ tôi có thể thêm một phương pháp (GetCalculationTask
) trả về một tác vụ bằng cách sử dụng Task.Run()
và thêm một sự kiện đồng bộ hóa tức thì cho một nút (MethodOne
).
Vui lòng sửa tôi nếu tôi sai, nhưng có vẻ như đây là lựa chọn duy nhất khi các lớp học ClassThatUsesACalculator
và Calculator
nằm trong thư viện mà tôi không sở hữu.
private Task GetCalculationTask(IProgress<CalculatorProgress> progress)
{
var calculator = new ClassThatUsesACalculator();
calculator.ProgressChanged += (s, e) =>
{
progress.Report(new CalculatorProgress(0));
};
return Task.Run(() =>
{
calculator.DoWork();
});
}
private async void MethodOne(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress> (UpdateProgressBar);
await GetCalculationTask(progress);
}
Trong trường hợp tôi sở hữu thư viện, tôi nghĩ có thêm hai tùy chọn, một trong số đó rất giống tùy chọn đầu tiên. Có lẽ do sự thiếu hiểu biết của tôi.
Tạo phương thức trên ClassThatUsesACalculator
đóng gói phương thức DoWork()
và sau đó gọi phương thức đó từ phương thức không đồng bộ trên biểu mẫu.
hay,
đóng gói các
LongRunningCalculation()
trên lớpCalculator
với mộtTask.Run()
.public Task<CalculatorResult> CalculateAsync() { return Task.Run(() => { return LongRunningCalculation(); }); }
Tạo một phương thức không đồng bộ trên
ClassThatUsesACalculator
cuộc gọi đang chờ phương thức mới được tạo.public async Task DoWorkAsync() { for (int i = 0; i < 10; i++) { var result = await calculator.CalculateAsync(); DoSomethingWithCalculationResult(result); DoLightWork(); OnProgressChanged(); } }
Tạo một phương pháp không đồng bộ về hình thức (
MethodThree
)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(); }
Bây giờ, theo ý kiến của tôi lựa chọn cuối cùng sẽ là tốt nhất như tôi sẽ vẫn kiểm soát nhiều hơn. Nhưng có lẽ tôi đang đi và muốn ý kiến của một ai đó hoặc con trỏ về điều này vì tôi chỉ có thể tìm thấy giải thích về cách tiêu thụ async, nhưng không bao giờ thực sự làm thế nào để xây dựng phương pháp cho người khác để tiêu thụ.
Câu hỏi của bạn thực sự dài và quá dài dòng - nó có thể hữu ích nếu bạn thu hẹp nó để giải thích ngắn gọn những gì bạn muốn biết. Nhân tiện, đối với những thứ nhanh chóng, 'async' không thực sự cần thiết. 'async' là tuyệt vời cho các nhiệm vụ I/O như truy cập một tệp, cơ sở dữ liệu hoặc dịch vụ web. Nhưng chi phí cho việc chạy nhanh các bit không phải là mã I/O thực sự có thể làm giảm hiệu suất. – mason