调度程序.产量优先级问题

我想在循环中更新 WPF 应用程序中某些 UI 元素的位置。每次迭代后,应重新呈现 UI 以使更改可见。更新过程可以随时使用取消令牌停止。由于取消是由用户执行的,因此 UI 必须保持对输入的响应。我写了以下方法来做到这一点:


public async Task DoStuff(CancellationToken token)

{

    do

    {

        DoLayoutUpdate();


        await Dispatcher.Yield(DispatcherPriority.Input);

    } while (!token.IsCancellationRequested);

}

这主要有效:UI在每次迭代后重新渲染,我可以单击按钮取消操作,以便输入也有效。问题是:如果没有输入并且没有要重新呈现的内容,则该方法会卡在 Yield 中。据推测,线程被阻塞,等待输入或呈现任务。


如果我将增加到 ,则该方法不会再卡住,但随后 UI 不会更新,输入不再被处理。DispatcherPriorityRender


我该如何解决这个问题?


HUX布斯
浏览 118回答 3
3回答

富国沪深

尝试 或 代替 。await Task.Delay(10);await Dispatcher.BeginInvoke(new Action(() => { }), System.Windows.Threading.DispatcherPriority.Input);Dispatcher.Yield这应该使 UI 线程有机会在执行循环时进行呈现。

慕仙森

或者无论你在哪个线程上运行,都有效的奇怪的怪物:        await Task.Run(() =>        {            Action action = () => { };            MainWindow.Dispatcher.Invoke(action,                 System.Windows.Threading.DispatcherPriority.Background);        });Dispatcher.Yield()在 UI 线程上工作正常。但它是一个静态方法,在 上运行,并且没有等效的非静态成员。Dispatcher.CurrentDispatcher

阿晨1998

如果我增加调度程序优先级以进行渲染,则该方法不会再卡住,但 UI 不会更新,输入也不会再得到处理。实际上,问题在于您在错误的方向上更改了优先级。将优先级设置为 将允许 WPF 完成其工作,然后最终安排继续以允许方法在 之后继续执行。DispatcherPriority.Backgroundawait即:public async Task DoStuff(CancellationToken token){    do    {        DoLayoutUpdate();        await Dispatcher.Yield(DispatcherPriority.Background);    } while (!token.IsCancellationRequested);}使用较高的优先级会导致过早地安排继续,从而为循环提供所有调度程序时间,优先于 WPF 需要执行的所有其他操作。当然,请注意,不带参数的调用也将默认为 using。无论哪种方式都工作正常。Dispatcher.Yield()DispatcherPriority.Background在接受的答案中提出的其他想法也会起作用,但与简单地屈服于正确请求的延续优先级相比,它们有点笨拙。
打开App,查看更多内容
随时随地看视频慕课网APP