请教高人,有关C# 多线程中使用Invoke更新listview 时死机的问题(第一次发帖,分数不多,请原谅)
我在Form 中有一个ListView,它根据不同的按钮(button1,button2,button3)显示不同的
内容(需要重新划分列);
还在Form中定义了一个插入行的涵数如名称insertListview(byte[] buff,int i,int j),
然后在另一个线程中使用form.invoke(new delegatename(insertListview,....)),它在线程中被循环调用.(它对应button1被按下时才显示).
出现问题如下:
当程还没有启动线程时,就先按button1,再启动线程,如果此时再去按其它按钮系统就会死机。
问题点数:0、回复次数:9Top
1 楼skyeenet(我不要当跑龙套的)回复于 2004-12-02 10:53:44 得分 0
SyncLock 楼主看看《操作系统》 就知道什么是临界资源 什么是 死锁 ……
多线程访问就要用 SyncLock 保证资源的排他访问 ……Top
2 楼dazhu2(【倚天不出,谁与争锋】)回复于 2004-12-02 11:04:13 得分 0
采用BeginInvoke()的方法,进行异步更新Top
3 楼sunismoon(痴心不改)回复于 2004-12-02 11:05:34 得分 0
我使用了 Monitor.Enter(listBiaozhi)和Monitor.Exit(listBiaozhi)Top
4 楼sunismoon(痴心不改)回复于 2004-12-02 11:06:15 得分 0
异步更新也不行Top
5 楼dazhu2(【倚天不出,谁与争锋】)回复于 2004-12-02 11:11:06 得分 0
参考以下:
private delegate void updatelistview(string [,] a);
private void listview_refresh(object sender,PingEventArgs e)
{
this.listView1.BeginInvoke(new updatelistview(dowork),new object []{e.ping_result});
}
private void dowork(string [,] b)
{
this.listView1.Items.Add(new ListViewItem(new string[]{b[0,0],b[0,1]}));
this.listView1.Refresh();
this.label5.Text="已扫描了"+this.listView1.Items.Count.ToString()+"台计算机,请稍等..";
if(this.listView1.Items.Count>=box)
{
this.label5.Visible=false;
thread_clear();
this.Cursor=System.Windows.Forms.Cursors.Default;
}
}Top
6 楼dazhu2(【倚天不出,谁与争锋】)回复于 2004-12-02 11:14:28 得分 0
关注Top
7 楼sunismoon(痴心不改)回复于 2004-12-02 11:20:30 得分 0
dazhu2(边城浪子(倚天不出,谁与争锋)) 你好,你贴子是在同一个线程内执行的,我的程序的更新命令是在另外一个线程(不是界面线程的),
界面中定义
public void InsertToEvent(byte[] buff,int len,DateTime time1,bool bRec)
{
Monitor.Enter(listBiaozhi);
if(listBiaozhi==5)
{
if(listView1.Items .Count >50)
listView1.Items .RemoveAt (0);
ListViewItem li = new ListViewItem ( ) ;
li.SubItems.Clear ( ) ;
if(bRec)
li.SubItems [0].BackColor =Color.AliceBlue ;
else
li.SubItems [0].BackColor =Color.Brown;
li.SubItems [1].BackColor =Color.CadetBlue;
listView1.Items .Add( li);
strbuilder.Length =0;
}
Monitor.Exit(listBiaozhi);
}
调用在另一个线程
formpo.listView1.Invoke (new myMethodDelegate(formpo.InsertToEvent ),new object []{buff,len,begin_cmdTime,true});Top
8 楼hhmmdd(懵懂)回复于 2004-12-02 14:47:04 得分 0
如果上面这些方法都不行,你可以试试在线程当中给form发一个自定义消息,然后在form的winproc中处理这个自定义消息的时候进行界面显示工作。Top
9 楼Korny(登峰)回复于 2004-12-12 12:34:17 得分 0
很早遇到过这类问题,一直没有深入的研究,其实Invoke或begininvoke是运行在后台的工作线程,并与UI窗体处于同一线程之中,可以在应用程序的任何地方调用,但由这种操作不具线程安全性,所以最好不要这么做,winform是基于win32单线程单元STA的,所以不是线程安全的。这意味着一旦窗体实例化,就无法在操作线程之间(包括由异步操作生成的后台线程)安全地来回转换。必须在窗体所在线程上调用窗体方法。为减缓这一问题的影响,CLR对Invoke方法提供了支持,该方法能够在线程之间编组调用。如果没有编组,最初代码会运行很好,但是常常引起应用程序的不稳定。
hhmmdd(懵懂) 的方法倒是一个不错的方法Top




