Dispatcher.Invoke from a new thread is locking my UI

做~自己de王妃 提交于 2019-12-05 21:22:27

The problem is that you're making it impossible for this to execute, since you're using Invoke.

Dispatcher.Invoke will not return until the UI thread processes. However, you've blocked the UI thread by calling _waitHandle.WaitOne();, and don't set the wait handle until AFTER this processes. The two effectively cause a dead lock.

If you switch this to use BeginInvoke instead, the UI will queue the element, the wait handle will set, THEN the label will update. It will work and not block, however.

Since the two previous posts already cover the problem in your code, just a suggestion: instead of

if (lblStatus.Dispatcher.Thread == Thread.CurrentThread)

try using

if (!lblStatus.CheckAccess())

It's cleaner and has the exact intent you want. Just read about it here.

You probably want to use BeginInvoke instead. Invoke will block the thread that called it until the UI thread has run the Action, and since you're setting the priority to Background, this could take some time.

Best solution I have found for .net 4.5+ is using SynchronizationContext Post

Example (Task.Run's can be as many as you want in parallel accessing UI):

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    var context = SynchronizationContext.Current;
    Task.Run(() =>
    {
        var i = 0;
        while (true)
        {
            context.Post((tmp) =>
            {
                uiText.Text = $"{i}";
            }), this);

            Thread.Sleep(1000);
            i++;

        }
    });

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!