0

我试图将调度程序包装在一个线程中。但结果不是我所期望的。我该如何解决这个问题?

    public void Start()
    {
        ThreadStart ts = inner;
        Thread wrapper = new Thread(ts);
        wrapper.Start();
    }

    private void inner()
    {
        _Runner.Dispatcher.Invoke(_Runner.Action, DispatcherPriority.Normal);
    }
4

7 回答 7

5

您没有向我们展示足够多的代码/对自己的解释不够好,无法提供一个好的答案,但我您的操作 ( _Runner.Action) 代价高昂且执行缓慢。如果是这样,这就是您的 UI 没有响应的原因。您实际上是在告诉 Dispatcher 在 UI 线程上运行该昂贵的操作,而您真正想做的是在后台线程上尽可能多地运行您的操作,然后Dispatcher仅在必要时通过唯一的方式编组回 UI 线程.

于 2009-06-10T12:05:56.923 回答
2

当您通过/在调度程序上触发操作时,会在 UI 线程上调用该操作。

我的猜测是您正在_Runner.Action函数中进行工作/处理,并且它正在占用 UI 线程。您必须在inner()函数中执行主要处理部分,然后调用 Dispatcher 以获取最终更新详细信息。

如果您绝对必须在调度程序上进行处理,请将您的流程分成更小的部分并为每个部分调用 Dispatcher.BeginInvoke() 以便可以在您的流程之间处理其他事件。

于 2009-06-10T12:06:13.473 回答
2

您需要将 Runner.Action 分成两部分 - 执行计算的长时间运行部分和更新 GUI 的部分。

完成后,您在后台线程中调用长时间运行的部分,并仅在 UI 更新部分使用调度程序。

顺便说一句,您还应该使用 BeginInvoke 而不是 Invoke。

如果 Runner.Action 的长时间运行部分正在更新 GUI,那么您就不能使用后台线程来解决您的问题 - 有针对缓慢 GUI 操作的解决方案,但它们会根据您正在尝试做什么而改变。

于 2009-06-10T14:55:37.423 回答
1

和这里的每个人所说的一样。

此外,您可能希望研究使用BackgroundWorker类。

于 2009-06-10T17:18:40.863 回答
1

这是一个示例,可让您使用多个 UI 线程运行 WPF 应用程序。我相信这会对你有所帮助。请参阅此http://eprystupa.wordpress.com/2008/07/28/running-wpf-application-with-multiple-ui-threads/

Thread lThread = new Thread(() =>
                   {
                        var lWnd = new Window1();
                        lWnd.Show();
                        lWnd.Closed += (sender2, e2) => lWnd.Dispatcher.InvokeShutdown();
                        System.Windows.Threading.Dispatcher.Run();
                   });
lThread.SetApartmentState(ApartmentState.STA);
lThread.Start();
于 2009-06-10T14:43:50.723 回答
1

这是我开始用于后台任务的...我没有使用它很长时间,所以我不知道是否有错误。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SSA.Utility
{
    public class BackgroundTaskManager : IDisposable
    {
        private System.Windows.Threading.Dispatcher _OwnerDispatcher;
        private System.Windows.Threading.Dispatcher _WorkerDispatcher;
        private System.Threading.Thread _WorkerThread;
        private Boolean _WorkerBusy;

        private System.Threading.EventWaitHandle _WorkerStarted = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.ManualReset);

        public BackgroundTaskManager()
        {
            _OwnerDispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
            _WorkerThread = new System.Threading.Thread(new System.Threading.ThreadStart(WorkerStart));
            _WorkerThread.Name = "BackgroundTaskManager:" + DateTime.Now.Ticks.ToString();
            _WorkerThread.IsBackground = true;
            _WorkerThread.Start();

            _WorkerStarted.WaitOne();
        }

        public Boolean IsBusy
        {
            get { return _WorkerBusy; }
        }

        public System.Windows.Threading.Dispatcher Dispatcher 
        {
            get {
                return _WorkerDispatcher;
            }
        }

        public System.Windows.Threading.Dispatcher OwnerDispatcher
        {
            get
            {
                return _OwnerDispatcher;
            }
        }


        private void WorkerStart()
        {
            _WorkerDispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
            _WorkerDispatcher.Hooks.DispatcherInactive += WorkDone;
            _WorkerDispatcher.Hooks.OperationPosted += WorkAdded;
            _WorkerStarted.Set();
            System.Windows.Threading.Dispatcher.Run();
        }

        private void WorkAdded(Object sender, System.Windows.Threading.DispatcherHookEventArgs e)
        {
            _WorkerBusy = true;
        }

        private void WorkDone(Object sender, EventArgs e)
        {
            _WorkerBusy = false;
        }

        public void Dispose()
        {
            if (_WorkerDispatcher != null)
            {
                _WorkerDispatcher.InvokeShutdown();
                _WorkerDispatcher = null;
            }
        }

    }
}


// Useage (not tested)

private SSA.Utility.BackgroundTaskManager _background = new SSA.Utility.BackgroundTaskManager();

public void LongTaskAsync() 
{
  _background.Dispatcher.BeginInvoke(new Action(LongTask), null);
}

public void LongTask() 
{
   System.Threading.Thread.Sleep(10000); // simulate a long task
   _background.OwnerDispatcher.BeginInvoke(new Action<STATUSCLASS>(LongTaskUpdate), statusobject);
}

public void LongTaskUpdate(STATUSCLASS statusobject) {

}
于 2011-08-22T16:24:36.513 回答
0

是的。_Runner.Action 是问题所在。Dispatcher 块中使用的一些长时间的方法。但解决方案是“不要在调度程序中使用与 UI 无关的任何线程”

于 2009-06-10T12:53:58.527 回答