C#wpf调度程序线程

时间:2013-11-12 12:16:29

标签: c# wpf multithreading dispatcher

我正在尝试创建一个新的Thread并在某些情况下让它进入睡眠状态,但是当我这样做时,主线程会睡眠,而不仅仅是我创建的那个。我使用的是Dispatcher.BeginInvoke但这只是为了从主线程“授予权限”来访问该方法。

它有效,因为它不会给我一个InvalidOperationException,但是当链接方法开始时,创建的线程的“焦点”会丢失。

我想我应该使用ManualResetEvent等待创建的Thread,但我不知道是怎么做的。我一直在寻找可能的解决方案,但没有人工作。

我认为这应该很容易,但我不能这样做。以下代码如下:

void EmpujeDispatcher(object objeto)
{
    this.Dispatcher.BeginInvoke(new Action<object>(Empuje), objeto);
}
private void Empuje(object objeto)
{
    Thread.Sleep(2000); MessageBox.Show("This should not freeze the window");

                Canvas Bacteria = objeto;
                double PosX = Canvas.GetLeft(Bacteria);//Posición del sender
                double PosY = Canvas.GetTop(Bacteria);//Lo mismo
                Bacterias BacteriaInstancia = InstanciaBacterias[Bacteria.Uid];//Se busca la bacteria para relacionarla con al instancia
                BacteriaInstancia.posX = PosX;
                BacteriaInstancia.posY = PosY;
                // BacteriaInstancia.Moverse();

                if (BacteriaInstancia.momemtum <= 0)
                {
                    Canvas.SetTop(Bacteria, PosY); Canvas.SetLeft(Bacteria, PosX);//Para el empuje
                    dispatcherTimer.Stop();
                }

                else
                {   //Rebote:
                    BacteriaInstancia.Posicion();
                    PosX = BacteriaInstancia.posX;
                    PosY = BacteriaInstancia.posY;
                    if (PosX + Bacteria.Width >= CanvasSimulador.Width) { BacteriaInstancia.direccionAnterior = BacteriaInstancia.direccion; BacteriaInstancia.direccion = 1; }
                    if (PosX <= 0) { BacteriaInstancia.direccionAnterior = BacteriaInstancia.direccion; BacteriaInstancia.direccion = 3; }
                    if (PosY + Bacteria.Height >= CanvasSimulador.Height) { PosY = CanvasSimulador.Height - Bacteria.Height; BacteriaInstancia.direccionAnterior = BacteriaInstancia.direccion; BacteriaInstancia.direccion = 2; }
                    if (PosY <= 0) { PosY = 1; BacteriaInstancia.direccionAnterior = BacteriaInstancia.direccion; BacteriaInstancia.direccion = 4; }
                    Canvas.SetTop(Bacteria, PosY); Canvas.SetLeft(Bacteria, PosX);

                    BacteriaInstancia.momemtum = Math.Sqrt(Math.Pow(BacteriaInstancia.Vfx, 2) + Math.Pow(BacteriaInstancia.Vfy, 2));
                    ControlFlujo = BacteriaInstancia.momemtum;




}
private void EmpujeEvent(object sender, MouseButtonEventArgs e)
{
    Thread TimerClockThread = new Thread(new ParameterizedThreadStart(EmpujeDispatcher));
    TimerClockThread.IsBackground = true;
    TimerClockThread.Start(sender);
}

这不是代码,因为在这个Dispatcher中没有任何意义,如果我创建没有调度程序的线程

TimerClockThread = new Thread( new ParameterizedThreadStart(Empuje));

效果很好......因为它是MessageBox,但在原版中我在“Empuje”中有很多代码。

感谢您的关注,希望您可以帮助我:)。

3 个答案:

答案 0 :(得分:3)

您的Dispatcher.Invoke强制在UI线程上调用您的Empuje方法。如果要更新屏幕,则应将调用移至后台线程:

TimerClockThread = new Thread( new ParameterizedThreadStart(Empuje));

private void Empuje(object objeto)
{
   Thread.Sleep(2000); 
   Dispatcher.BeginInvoke(new Action(() => {
       MessageBox.Show("This should not freeze the window");
   }));
   //........ Do stuff.....
}

但是在带有async的现代C#中,您可以删除所有代码,而不是写:

private async void EmpujeEvent(object sender, MouseButtonEventArgs e)
{
    await Task.Delay(2000);
    MessageBox.Show(...);
}

答案 1 :(得分:0)

您的函数EmpujeDispatcher正在使用与您的GUI线程关联的相同调度程序。这意味着你告诉调度员异步执行Empuje,不幸的是它在GUI线程上执行。至少这就是我的想法。

答案 2 :(得分:0)

BackgroundWorker非常适合此任务。实现它的最短代码如下所示:

var worker = new BackgroundWorker();
worker.DoWork += (s,e) => 
{
    Thread.Sleep(2000);
    // Do Stuff...
};
worker.RunWorkerAsync();

搜索SO会产生大量关于BackgroundWorker的Q&amp; A(即thisthis