为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
HUX布斯 2022-09-04 16:35:19
我想在循环中更新 WPF 应用程序中某些 UI 元素的位置。每次迭代后,应重新呈现 UI 以使更改可见。更新过程可以随时使用取消令牌停止。由于取消是由用户执行的,因此 UI 必须保持对输入的响应。我写了以下方法来做到这一点:public async Task DoStuff(CancellationToken token){    do    {        DoLayoutUpdate();        await Dispatcher.Yield(DispatcherPriority.Input);    } while (!token.IsCancellationRequested);}这主要有效:UI在每次迭代后重新渲染,我可以单击按钮取消操作,以便输入也有效。问题是:如果没有输入并且没有要重新呈现的内容,则该方法会卡在 Yield 中。据推测,线程被阻塞,等待输入或呈现任务。如果我将增加到 ,则该方法不会再卡住,但随后 UI 不会更新,输入不再被处理。DispatcherPriorityRender我该如何解决这个问题?
查看完整描述

3 回答

?
富国沪深

TA贡献1790条经验 获得超9个赞

尝试 或 代替 。await Task.Delay(10);await Dispatcher.BeginInvoke(new Action(() => { }), System.Windows.Threading.DispatcherPriority.Input);Dispatcher.Yield

这应该使 UI 线程有机会在执行循环时进行呈现。


查看完整回答
反对 回复 2022-09-04
?
慕仙森

TA贡献1827条经验 获得超7个赞

或者无论你在哪个线程上运行,都有效的奇怪的怪物:


        await Task.Run(() =>

        {

            Action action = () => { };

            MainWindow.Dispatcher.Invoke(action, 

                System.Windows.Threading.DispatcherPriority.Background);

        });

Dispatcher.Yield()在 UI 线程上工作正常。但它是一个静态方法,在 上运行,并且没有等效的非静态成员。Dispatcher.CurrentDispatcher


查看完整回答
反对 回复 2022-09-04
?
阿晨1998

TA贡献2037条经验 获得超6个赞

如果我增加调度程序优先级以进行渲染,则该方法不会再卡住,但 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


在接受的答案中提出的其他想法也会起作用,但与简单地屈服于正确请求的延续优先级相比,它们有点笨拙。


查看完整回答
反对 回复 2022-09-04
  • 3 回答
  • 0 关注
  • 116 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信