【问题标题】:How can I access UI element while Backgroundworker with Dispatcher?如何在使用 Dispatcher 的 Backgroundworker 访问 UI 元素?
【发布时间】:2017-07-19 10:17:28
【问题描述】:

enter image description here我知道这不是关于访问 UI 线程的第一个问题,但我没有找到解决问题的答案。

在调用示例方法时,它会像带有中止按钮的消息框一样显示。如果我单击中止按钮,它将不会被中止按钮单击事件。这里警报框 UI 冻结。所以我们不能点击那个。

如果我删除调度程序行,它将正常工作。但我希望该行用于执行 AddQueryIntoTable 方法。如果该方法将在 100 毫秒后调用,它将完美地检索数据。

所以我将设置 100 毫秒作为睡眠模式(注释行)它会正常工作。但我认为这不是完美的解决方案。

提前致谢。

public void SampleMethod()
     {   
        CancelSupportedBackgroundWorker backGroundWorker = new CancelSupportedBackgroundWorker { WorkerSupportsCancellation = true };
        CancellationTokenSource source = new CancellationTokenSource();
        AlertBox alertBox = new AlertBox
        {
            WaitingText = "Loading Indicator",
            WaitingHeaderText = "It is Loading",
        };
        alertBox.IsBusy = true;
        alertBox.AbortButton.Click += (obje, arg) =>
        {
            MessageBox.Show("Hit");
        };
         backGroundWorker.DoWork += (obj, e) =>
        {
        App.Current.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(
             delegate ()
             {
                 try
                 {
                     if (info == null)
                     {
                     //Thread.sleep(100);
                     arg.result = AddqueryintoTable((CancellationToken)e.Argument);

                    if (backGroundWorker.CancellationPending)
                         {
                             e.Cancel = true;
                             return;
                         }
                     }
                 }
                 catch (ThreadAbortException)
                 {
                     Dispatcher.Invoke(() =>
                     {
                         alertBox.IsBusy = false;
                     }, System.Windows.Threading.DispatcherPriority.Background);
                     e.Cancel = true;
                 }
             }));
        };
        backGroundWorker.RunWorkerCompleted += (obj, arg) =>
        {
            if (arg.Cancelled)
            {
                alertBox.IsBusy = false;
                return;
            }
            alertBox.IsBusy = false;      
            if (arg != null && arg.Result != null)
            {
                SetReport(arg.Result);
            }          
        };
        backGroundWorker.RunWorkerAsync(source.Token);

}

【问题讨论】:

  • 另外,我会将调度程序优先级更改为无法正常工作的各种类型
  • 如果您经常使用调度程序调用不同线程上的操作,为什么还要使用 BackgroundWorker?
  • @lan H,我需要使用do work方法的结果设置报告。
  • 但是你为什么要调度 整个 DoWork 方法呢?
  • BackgroundWorker 旨在异步运行。在这里,您将整个 DoWork 方法调用到调度程序,使 BackgroundWorker 不再异步工作。

标签: c# multithreading backgroundworker dispatcher


【解决方案1】:

尽量不要将整个 DoWork 方法放在 Dispatcher 调用中,而是只对其调用单个操作。

backGroundWorker.DoWork += (obj, e) =>
{
    try
    {
        if (info == null)
        {
            Thread.Sleep(100);
            App.Current.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action( delegate ()
            {
                arg.result = AddqueryintoTable((CancellationToken)e.Argument);
            }));

            if (backGroundWorker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
        }
    }
    catch (ThreadAbortException)
    {
        Dispatcher.Invoke(() =>
        {
            alertBox.IsBusy = false;
        }, System.Windows.Threading.DispatcherPriority.Background);
        e.Cancel = true;
    }  
};

【讨论】:

  • @lan H,我按照您的解决方案进行了尝试。但是在单击该按钮时,警报框中的中止按钮无法点击。我还附上了有问题的警报框图像
猜你喜欢
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多