winform 多线程 UI假死问题

zarm.design 2013-09-29 12:33:10
正在做一个winform程序,选中listview的一行,会有一个比较耗时的操作,操作结束后会修改10几个label的值,发现选择了listview某行后,经常UI假死,选择其他的记录会停顿滞后。我想新建一个线程去处理它,每个label控件都要写委托吗?10几个实在是太多了,有没有更好的办法统一做?不容易造成UI假死
...全文
344 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Champion_Chen 2013-10-16
  • 打赏
  • 举报
回复
更好做法:(想想只写自己的猜想,好像有点不太负责.现在正好在读的东西里面有类似的代码http://www.ladislavmrnka.com/2012/09/entity-framework-and-pessimistic-concurrency/

private static void Method() {
    // Handles are used only to wait for both workers to complete
    var handles = new WaitHandle[] {
        new ManualResetEvent(false),
        new ManualResetEvent(false),
    };
 
    // Worker's job
    WaitCallback job = state => {
        DoSomethings();
        // Signal to the main thread that the worker has completed
        ((ManualResetEvent)state).Set();
        
    };
 
    // Run workers
    ThreadPool.QueueUserWorkItem(job, handles[0]);
    ThreadPool.QueueUserWorkItem(job, handles[1]);
 
    // Wait for both workers to complete
    WaitHandle.WaitAll(handles);
}
Champion_Chen 2013-10-16
  • 打赏
  • 举报
回复
引用 4 楼 duxcms 的回复:
[quote=引用 3 楼 cp2516 的回复:] 1 把方法这样写:
 void  Test(string msg)
        {
            if (InvokeRequired)
            {
                this.Invoke(new Action<string>(Logging2),msg);
            }
            else
            {
               Logging2( msg);
            }
        }

        private void Logging2(string msg)
        {
          //----这里写你对UI的实际操作
        }
2 另一线程调用:以 ThreadPool.QueueUserWorkItem为例
 ThreadPool.QueueUserWorkItem(Somemethod);
3 关键在于 if (InvokeRequired) { this.Invoke(new Action<string>(Logging2),msg); }
这种做法排队列,是不会造成2楼所说的“奇怪现象”?[/quote] 可恶的设置,自己的回复竟然无法编辑。只好再引用一遍了。 那样做是无法解决Winform主线程后面有多个线程运算,执行速度不一,造成数据不一致的问题。但可以解决一个后台运算线程运算完了然后更新UI。 对于奇怪现象,应该会使用线程间的共享变量(volatile 标记)做标识,以控制不同线程的执行顺序或者返回顺序吧,如

线程N:
DoSomeCaculation();
autoResetEventN.WaitOne();
DoSomethingOfUpdateUI();
volatileField=N+1;

主线程:
while(true)
{
  if(volatileField==SomeValue)break;
  if(volatileField==1)autoResetEvent1.Set();
  if(volatileField==2)autoResetEvent2.Set();
  ...
}
。 (多线程我了解得也不多,上面也只是我的猜想)。
Champion_Chen 2013-10-16
  • 打赏
  • 举报
回复
引用 4 楼 duxcms 的回复:
[quote=引用 3 楼 cp2516 的回复:] 1 把方法这样写:
 void  Test(string msg)
        {
            if (InvokeRequired)
            {
                this.Invoke(new Action<string>(Logging2),msg);
            }
            else
            {
               Logging2( msg);
            }
        }

        private void Logging2(string msg)
        {
          //----这里写你对UI的实际操作
        }
2 另一线程调用:以 ThreadPool.QueueUserWorkItem为例
 ThreadPool.QueueUserWorkItem(Somemethod);
3 关键在于 if (InvokeRequired) { this.Invoke(new Action<string>(Logging2),msg); }
这种做法排队列,是不会造成2楼所说的“奇怪现象”?[/quote] 对于简单的,例如一个主线程一个运算线程,可以用一个类似
volatile bool _completedFlag
解决。在运算线程运算完后,设置完_completedFlag为true后,主线程才会被激活,否则一直等待。
threenewbee 2013-09-29
  • 打赏
  • 举报
回复
不要以为“不造成UI假死”就是你的终极目标,这个要根据你的需求来定。 如果你使用异步处理,有可能会导致当你选中1,你的程序异步处理选择1的操作,然后你选中2,你的程序异步处理选择2的操作,并且先返回,异步处理选择1的操作后返回,导致用户选择了2,看到的是1的奇怪现象。
迷迷520 2013-09-29
  • 打赏
  • 举报
回复
大的数据里。写到 异步里处理。处理完后。反映给 UI
zarm.design 2013-09-29
  • 打赏
  • 举报
回复
引用 3 楼 cp2516 的回复:
1 把方法这样写:
 void  Test(string msg)
        {
            if (InvokeRequired)
            {
                this.Invoke(new Action<string>(Logging2),msg);
            }
            else
            {
               Logging2( msg);
            }
        }

        private void Logging2(string msg)
        {
          //----这里写你对UI的实际操作
        }
2 另一线程调用:以 ThreadPool.QueueUserWorkItem为例
 ThreadPool.QueueUserWorkItem(Somemethod);
3 关键在于 if (InvokeRequired) { this.Invoke(new Action<string>(Logging2),msg); }
这种做法排队列,是不会造成2楼所说的“奇怪现象”?
Champion_Chen 2013-09-29
  • 打赏
  • 举报
回复
1 把方法这样写:
 void  Test(string msg)
        {
            if (InvokeRequired)
            {
                this.Invoke(new Action<string>(Logging2),msg);
            }
            else
            {
               Logging2( msg);
            }
        }

        private void Logging2(string msg)
        {
          //----这里写你对UI的实际操作
        }
2 另一线程调用:以 ThreadPool.QueueUserWorkItem为例
 ThreadPool.QueueUserWorkItem(Somemethod);
3 关键在于 if (InvokeRequired) { this.Invoke(new Action<string>(Logging2),msg); }
zarm.design 2013-09-29
  • 打赏
  • 举报
回复
引用 1 楼 caozhy 的回复:
不要以为“不造成UI假死”就是你的终极目标,这个要根据你的需求来定。 如果你使用异步处理,有可能会导致当你选中1,你的程序异步处理选择1的操作,然后你选中2,你的程序异步处理选择2的操作,并且先返回,异步处理选择1的操作后返回,导致用户选择了2,看到的是1的奇怪现象。
像我这种情况应该怎么处理呢?

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧