在一个C# WinForms应用程序中,我试图将图像抖动操作移动到后台线程中,并在窗体中添加一个进度条,以显示处理状态。到目前为止,我已经实现了所有这些,但我不知道如何将结果字节返回到主线程中。
旧代码:
interface ImageConverter {
MCBlockVariant[,] Convert(Bitmap image, Size size, ImageDitherer ditherer);
}
private void btnConvert_Click(object sender, EventArgs e) {
ImageDitherer d = null;
if (cbDithering.Checked) {
d = (ImageDitherer)cmbDitherers.SelectedValue;
d.Reset(scaledSize);
}
//TODO: P1 show progress bar somewhere
MCBlockVariant[,] blocks = imageConverter.Convert(image, scaledSize, d);
MCPACResultForm form = new MCPACResultForm(blocks, palette);
form.Show();
}
我能够成功地让这个进程在后台运行,通过改变方法签名和调用主窗体线程上的进度条,在整个进程中更新它。这一切都是毫无疑问的。我只是不知道如何将该过程的结果提升回主窗体线程,以便将结果提供给新的输出窗体。
新增代码:
interface ImageConverter {
Task<MCBlockVariant[,]> Convert(Bitmap image, Size size, ImageDitherer ditherer, ProgressBar progress);
}
private async void btnConvert_ClickAsync(object sender, EventArgs e) {
ImageDitherer d = null;
if (cbDithering.Checked) {
d = (ImageDitherer)cmbDitherers.SelectedValue;
d.Reset(scaledSize);
}
Task<MCBlockVariant[,]> blocks = Task.FromResult(new MCBlockVariant[0, 0]);
await Task.Run(() => {
blocks = imageConverter.Convert(image, scaledSize, d, progressBarConvertImage);
});
// NOTE: This no longer works because `await` doesn't actually wait.
// MCPACResultForm form = new MCPACResultForm(blocks.Result, palette);
// form.Show();
}
1条答案
按热度按时间r6l8ljro1#
你这样做不对。
Task.FromResult
是一个完全不符合逻辑的函数,在你得到任何结果之前这样做是没有意义的,而且在任何情况下都是用来为 * 同步 * 函数创建结果的。从lambda中返回一个值。
await
意味着控制权被交回给调用代码,函数的继续被调度到ThreadPool上。注意再入问题。