im new here and always find helpful threads here, but not in this case. I'm having an issue with my program using threads. In special, my thread is doing some image pattern in the backround and everything seems to be fine. It also works an undefined time (sometimes 15 s, sometimes minutes) without any exception or freeze or whatever. But then my GUI freezes, not my whole GUI, just the GUI parts updated from the thread. Two other pictureboxes are working fine(streaming a video), but the rest isnt working. Trying to stop the thread where it is, works, but starting it from there makes my program collapse. There arn't eny exceptions thrown. Every GUI element is updated via Invoke() if necessary. I only work on a copy of the Picture to avoid any lockmodes or anything else. Also i try to let the UI doing what it needs to do (DoEvents()) Some ideas? Code:
namespace My.Name.Space
{
public class MyThread : MyThreadBase
{
public MyThread ( getting object s from the form for updating UI elements)
{
//referencing objects
Stopwatch.Start();
}
//example Method for UI updating
private void UpdateRobot1Box(int angle, int x, int y)
{
if (_rob1.InvokeRequired)
{
_rob1.Invoke(new Action(() => _rob1.Clear()));
_rob1.Invoke(new Action(() => _rob1.Text = angle.ToString() + "°, X:" + x.ToString() + ", Y:" + y.ToString()));
}
else
{
_rob1.Clear();
_rob1.Text = angle.ToString() + "°, X:" + x.ToString() + ", Y:" + y.ToString();
}
}
protected override void Loop(CancellationToken token)
{
while(!token.IsCancellationRequested)
{
if( PictureBox != null && Stopwatch.ElapsedMilliseconds >= tick)
{
//DoWork
Application.DoEvents();
}
else
{
Thread.Sleep(1);
}
}
}
}
}
}
Edit 1:
MyThreadBase:
namespace My.Name.Space
{
public abstract class MyThreadBase : DisposableBase//just some simple gc stuff
{
private CancellationTokenSource _cancellationTokenSource;
public bool IsAlive
{
get { return _cancellationTokenSource != null; }
}
public event Action<Object, Exception> UnhandledException;
public void Start()
{
if (_cancellationTokenSource != null)
return;
lock (this)
{
if (_cancellationTokenSource != null)
return;
_cancellationTokenSource = new CancellationTokenSource();
var thread = new Thread(RunLoop) {Name = GetType().Name};
thread.Start();
}
}
public void Stop()
{
if (_cancellationTokenSource == null)
return;
lock (this)
{
if (_cancellationTokenSource == null)
return;
_cancellationTokenSource.Cancel();
}
}
public void Join()
{
while (IsAlive) Thread.Sleep(1);
}
private void RunLoop()
{
try
{
CancellationToken token = _cancellationTokenSource.Token;
Loop(token);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception exception)
{
OnException(exception);
}
finally
{
lock (this)
{
CancellationTokenSource cancellationTokenSource = _cancellationTokenSource;
_cancellationTokenSource = null;
cancellationTokenSource.Dispose();
}
}
}
protected abstract void Loop(CancellationToken token);
protected virtual void OnException(Exception exception)
{
Trace.TraceError("{0} - Exception: {1}", GetType(), exception.Message);
Trace.TraceError(exception.StackTrace);
OnUnhandledException(exception);
}
protected virtual void OnUnhandledException(Exception exception)
{
if (UnhandledException != null)
UnhandledException(this, exception);
}
protected override void DisposeOverride()
{
Stop();
}
}
The UpdateRobot1Box is called in a switch-case construct within the thread. I got a little for-squence where I go through my list of own created objects to decide what to write in my textbox.