我是新来的,总是在这里找到有用的线程,但不是在这种情况下。我的程序使用线程时遇到问题。特别是,我的线程在背景中做了一些图像模式,一切似乎都很好。 它也可以在未定义的时间内工作(有时是15秒,有时是几分钟),没有任何异常或冻结或其他任何情况。但是我的GUI冻结了,而不是我的整个GUI,只是从线程更新的GUI部分。另外两个图片盒工作正常(流式传输视频),但其余的都没有工作。 试图阻止线程在哪里工作,但从那里开始使我的程序崩溃。 没有引发异常的例外。如有必要,每个GUI元素都通过Invoke()更新。我只处理图片的副本以避免任何锁模式或其他任何东西。我也尝试让UI做它需要做的事情(DoEvents()) 一些想法? 代码:
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);
}
}
}
}
}
}
编辑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();
}
}
在线程内的switch-case结构中调用UpdateRobot1Box。我得到了一些顺序,我通过我自己创建的对象列表来决定在我的文本框中写什么。
答案 0 :(得分:0)
在主窗体类中创建一个方法来执行UI更新操作:
private void AsyncFormUpdate(Action action)
{
if (this.InvokeRequired)
{
this.Invoke(action, null);
}
else
{
action();
}
}
在适当的位置使用它确保InvokeRequired正常运行,并且代码更好地封装。
接下来很简单。使用带有反馈的异步调用委托来报告角度并协调对UI的更改,您将实际调用AsyncFormUpdate方法。 这里显示了一个很好的例子:
http://www.csharp-examples.net/asynchronous-method-progress/
在那里他们更新进度,你将更新角度和X / Y坐标。