Reputation: 71
I am trying to create a new Thread
and put it to sleep in some occasions, but when I do it the main thread sleep, not only the one that I had created. I am using a Dispatcher.BeginInvoke
but this is only to "give a permission" from the main thread to access to the method.
It works because it does not give me an InvalidOperationException
, but the "focus" of the created thread losses when the linked method start.
I think I should use a ManualResetEvent
to wait for the created Thread
, but I do not know how doing it. I have been looking for possible solutions but no one works.
I think this should be easy but i cannot do it. The following code is Below:
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);
}
This is not exacly the code because in this one Dispatcher
does not have any sense, if I create the Thread without dispatcher
TimerClockThread = new Thread( new ParameterizedThreadStart(Empuje));
It works well... because it's a MessageBox
, but in the original I have a lot of code inside of the "Empuje".
Thanks for your attention and hopefully you can help me :)
Upvotes: 1
Views: 20446
Reputation: 27105
Your Dispatcher.Invoke
forces your Empuje
method to be called on the UI thread. If you want to update the screen, you should move the call to the background thread:
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.....
}
In modern C# with async
however, you can remove all code and instead write:
private async void EmpujeEvent(object sender, MouseButtonEventArgs e)
{
await Task.Delay(2000);
MessageBox.Show(...);
}
Upvotes: 4
Reputation: 23310
A BackgroundWorker
is quite fit for this task. The shortest piece of code to implement it looks like this:
var worker = new BackgroundWorker();
worker.DoWork += (s,e) =>
{
Thread.Sleep(2000);
// Do Stuff...
};
worker.RunWorkerAsync();
Searching SO will yield a plethora of Q&A about the BackgroundWorker
(i.e. this or this)
Upvotes: 0
Reputation: 604
Your function EmpujeDispatcher is using the same dispatcher that your GUI thread is associated with. That means you are telling the dispatcher to execute Empuje asynchronously, unfortunately it is executed on the GUI thread. At least that's what I think.
Upvotes: 0