2012-09-17 33 views
2

我有一個線程與類組合的問題。 對於我的問題,我做了一個簡單的代碼來解釋我的問題。線程交叉類添加項目列表框

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace RemoteMonitorServer 
{ 
    public partial class RemoteMonitor : Form 
    { 
     Thread cThread; 
     Server cServer; 

     public RemoteMonitor() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      WriteLog("Programm started!"); 

      cServer = new Server(); 
      cThread = new Thread(new ThreadStart(cServer.StartServer)); 
      cThread.IsBackground = true; 
      cThread.Start(); 
     } 

     public void WriteLog(string sText) 
     { 
      MessageBox.Show(sText); 
      listBox1.Items.Add(sText); 
     } 
    } 
} 

類具有下面的代碼:「PROGRAMM開始」

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace RemoteMonitorServer 
{ 
    class Server 
    { 
     public void StartServer() 
     { 
      RemoteMonitor cTest = new RemoteMonitor(); 

      cTest.WriteLog("Thread started!"); 
     } 
    } 
} 

現在,當我開始這個代碼,列表框確實得到但不是「線程開始!」。 雖然我得到兩個MessageBox消息,所以我相信該方法正在被調用。 在Visual Studio 2010中沒有錯誤,有人可以告訴我我在做什麼錯誤嗎?

+1

這是因爲你從運行'StartServer'的線程對'listBox1.Items.Add'有一個無效的跨線程調用。不知道爲什麼它沒有拋出異常 - 你是否禁用了無效的跨線程調用檢查? –

+0

不,我沒有設置checkforillegalcrossthreadcalls爲false。 – SmartGuyz

回答

0

好吧,我終於得到了它,它與RemoteMonitor的實例做:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace RemoteMonitor 
{ 
    public partial class RemoteMonitor : Form 
    { 
     Thread cThread; 
     Server cServer; 

     public RemoteMonitor() 
     { 
      InitializeComponent(); 
     } 

     private void RemoteMonitor_Load(object sender, EventArgs e) 
     { 
      WriteLog("Programm started!"); 

      cServer = new Server(); 
      cThread = new Thread(() => cServer.StartServer(this)); 
      cThread.Start(); 
     } 

     public void WriteLog(string sText) 
     { 
      if (InvokeRequired) 
      { 
       Action action =() => lsbLogger.Items.Add(sText); 
       lsbLogger.Invoke(action); 
      } 
      else 
      { 
       lsbLogger.Items.Add(sText); 
      } 
     } 
    } 
} 

和類:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace RemoteMonitor 
{ 
    class Server 
    { 
     public void StartServer(RemoteMonitor cRemoteMonitor) 
     { 
      cRemoteMonitor.WriteLog("Thread started!"); 
     } 
    } 
} 

它像一個魅力,感謝您的答案a nd評論!

0

您可以使用SynchronizationContext將您的呼叫同步到UI。

// get a sync context 
private readonly SynchronizationContext _sync = SynchronizationContext.Current; 

然後,送法到線程池排隊的工作:

public void WriteLog(string sText) 
    { 
     _sync.Send((state) => { 
      MessageBox.Show(sText); 
      listBox1.Items.Add(sText); 
     }, null); 
    } 

更多在我提供給瞭解SendPost方法之間的差異的聯繫以及上例中state對象的用法。

2
public delegate void RunAtFormThreadCallBack(Control control, RunningAtFormThread method); 
private void RunAtFormThread(Control control, RunningAtFormThread method) 
{ 

     if (control.InvokeRequired) 
     { 
      var callback = new RunAtFormThreadCallBack(RunAtFormThread); 
      control.Invoke(callback, new object[] { control, method }); 
     } 
     else 
      method.Invoke(); 
} 

用法:

RunAtFormThread(listBox1, delegate 
          { 
    // executing at control thread... 
    listBox1.Items.Add(sText); 
    MessageBox.Show(sText); 
}); 
+0

我無法讓它工作,仍然沒有錯誤。 當我調試它並把mmbox放在「method.Invoke();」之前,那麼mmbox會出現,但沒有任何列表框。 – SmartGuyz