c# wpf dispatch with async lambda

bihw5rsg  于 2023-06-24  发布在  C#
关注(0)|答案(2)|浏览(181)

我正在使用WebView2控制器的PrintAsync()函数打印PDF。这个pdf是在幕后准备的,所以用户可能会要求在它准备好之前打印它。对于这个场景,我已经挂接了一个事件,当正在准备的pdf的异步任务完成时,该事件将触发。
在UI中调用以下代码,以便在pdf准备就绪后打印,但由于可能从触发事件的其他线程调用它,因此必须通过调度程序调用它。这似乎是工作时,从UI本身(即)调用。如果用户单击按钮时pdf已经准备好了),但从事件处理程序调用时 * 不是 *(PrintAsync在一瞬间返回,结果是一个空的1页pdf)。
我在google上搜索了两个版本:

//Version 1 with InvokeAsync and unwrapping.
private async Task printAll()
{
    CoreWebView2PrintStatus printStatus = CoreWebView2PrintStatus.OtherError;

    printStatus = await Dispatcher.InvokeAsync(async () =>
    {
        dummyWebView.Source = m_viewModel.renderedPdfForAllCalculations;
        return await dummyWebView.CoreWebView2.PrintAsync(m_printAllPrintSettings);
    }).Task.Unwrap();
    
    if (printStatus != CoreWebView2PrintStatus.Succeeded)
    {
        // show message
    }
}

// Version 2 with Invoke. In this scenario, PrintAsync returns almost immediately and results in an empty 1-page pdf.
private async Task printAll()
{
    CoreWebView2PrintStatus printStatus = CoreWebView2PrintStatus.OtherError;

    await Dispatcher.Invoke(async () =>
    {
        dummyWebView.Source = m_viewModel.renderedPdfForAllCalculations;
        printStatus = await dummyWebView.CoreWebView2.PrintAsync(m_printAllPrintSettings);
    });
    
    if (printStatus != CoreWebView2PrintStatus.Succeeded)
    {
        // show message
    }
}
sgtfey8w

sgtfey8w1#

听起来它需要在UI线程上调用。通过将UI线程的分派器注入到需要在UI线程上执行操作的对象中,我成功地处理了类似的情况。
示例化(在主线程上)如下所示:

private readonly Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;

像这样调用:

_mainDispatcher.Invoke((Action)delegate
{

        // Do the stuff on the main thread

});
y0u0uwnf

y0u0uwnf2#

使用接受Task<T>Dispatcher.Invoke方法的重载:

printStatus = await Dispatcher.Invoke<Task<CoreWebView2PrintStatus>>(async () =>
{
    dummyWebView.Source = m_viewModel.renderedPdfForAllCalculations;
    return await dummyWebView.CoreWebView2.PrintAsync(m_printAllPrintSettings);
});

相关问题