2013-11-12 2 views
1

Я пытаюсь создать новый Thread и поместить его в сон в некоторых случаях, но когда я делаю это, основной поток сна, а не только тот, который я создал. Я использую Dispatcher.BeginInvoke, но это только для того, чтобы «дать разрешение» из основного потока для доступа к методу.C# wpf dispatcher thread

Это работает, потому что это не дает мне 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); 
} 

Это не exacly кода, потому что в этом один Dispatcher не имеет никакого смысла, если я создаю тему без диспетчерских

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

Это хорошо работает ... потому что это MessageBox, но в оригинале у меня много кода внутри «Empuje».

Спасибо за внимание и надеюсь, вы можете помочь мне :)

+0

Я думаю, пропустил что-л. Можете ли вы объяснить, в каком случае должна быть задержка? и что вы говорите: «Это не должно замораживать окно». какое окно? сообщение или какой? –

+1

Метод 'Empuje' работает в потоке' Dispatcher' (UI/Main thread), так как он был вызван через 'Dispatcher.BeginInvoke' и с вашим вызовом' Thread.Sleep (2000) 'вы по существу ставите' Dispatcher' (UI)/Основной поток). Какова фактическая/оригинальная проблема, которую вы пытались решить таким образом? – sthotakura

+0

«Это не должно замораживать окно» = «Это не должно замораживать главную тему», нить, которая должна спать, должна быть TimerClockThread, а не основной Thread. –

ответ

3

ваших Dispatcher.Invoke сил ваш метод 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..... 
} 

В современном C# с async однако, вы можете удалить весь код и вместо того, чтобы писать:

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

Вашей функция EmpujeDispatcher использует тот же диспетчер, что ваш GUI поток связан. Это означает, что вы говорите диспетчеру выполнить Empuje асинхронно, к сожалению, он выполняется в потоке графического интерфейса. По крайней мере, это то, что я думаю.

0

A BackgroundWorker вполне подходит для выполнения этой задачи. Самый короткий фрагмент кода, чтобы реализовать это выглядит следующим образом:

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

Поиск SO даст множество Q & А о BackgroundWorker (т.е. this или this)

Смежные вопросы