我试图将调度程序包装在一个线程中。但结果并不是我所期待的。我该如何解决这个问题呢?
public void Start()
{
ThreadStart ts = inner;
Thread wrapper = new Thread(ts);
wrapper.Start();
}
private void inner()
{
_Runner.Dispatcher.Invoke(_Runner.Action, DispatcherPriority.Normal);
}
答案 0 :(得分:5)
你没有向我们展示足够的代码/解释自己能够提供一个好的答案,但我猜测你的行动(_Runner.Action
)是昂贵的,而且很慢执行。如果是这样,那就是您的UI没有响应的原因。你实际上是在告诉Dispatcher在UI线程上运行那个昂贵的操作,当你真正想做的事情是在后台线程上尽可能多地运行你的操作,然后通过{{1编组回到UI线程只在必要时才使用。
答案 1 :(得分:2)
当您通过/向调度程序触发操作时,将在UI线程上调用该操作。
我的猜测是你正在_Runner.Action
函数中进行工作/处理,它正在占用UI线程。您必须在inner()
函数中执行主要处理部分,然后调用Dispatcher以获取最终更新详细信息。
如果您绝对必须处理调度程序,请将您的流程分解为更小的部分并为每个部分调用Dispatcher.BeginInvoke(),以便在您的流程之间处理其他事件。
答案 2 :(得分:2)
您需要将Runner.Action分为两部分 - 执行计算的长时间运行部分和更新GUI的部分。
执行此操作后,您可以在后台线程中调用长时间运行的部分,并仅在UI更新部分上使用调度程序。
顺便说一下,你也应该使用BeginInvoke而不是Invoke。
如果Runner.Action的长时间运行部分正在更新GUI而不是使用后台线程来解决您的问题 - 有慢速GUI操作的解决方案,但它们会根据您的具体操作而改变。
答案 3 :(得分: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();
答案 4 :(得分:1)
同样在座的人都说过了。
此外,您可能希望使用BackgroundWorker类。
答案 5 :(得分: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) {
}
答案 6 :(得分:0)
是。 _Runner.Action是问题所在。 Dispatcher块中使用的一些长时间方法。但解决方案是“不要在调度程序中使用与UI无关的任何线程”