冻结GUI元素

时间:2014-03-06 19:45:40

标签: c# multithreading user-interface freeze

我是新来的,总是在这里找到有用的线程,但不是在这种情况下。我的程序使用线程时遇到问题。特别是,我的线程在背景中做了一些图像模式,一切似乎都很好。 它也可以在未定义的时间内工作(有时是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。我得到了一些顺序,我通过我自己创建的对象列表来决定在我的文本框中写什么。

1 个答案:

答案 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坐标。