winforms 如何使用`await`从一个C#函数调用中获得结果?

xoshrz7s  于 2023-10-23  发布在  C#
关注(0)|答案(1)|浏览(128)

在一个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();
}
r6l8ljro

r6l8ljro1#

你这样做不对。Task.FromResult是一个完全不符合逻辑的函数,在你得到任何结果之前这样做是没有意义的,而且在任何情况下都是用来为 * 同步 * 函数创建结果的。
从lambda中返回一个值。

MCBlockVariant[,] blocks = await Task.Run(() => {
        imageConverter.Convert(image, scaledSize, d, progressBarConvertImage);
    });

// do stuff with result

await意味着控制权被交回给调用代码,函数的继续被调度到ThreadPool上。注意再入问题。

相关问题