2009-04-25 70 views
1

直到這一刻我用這個方法來調用:如果窗體未處於活動狀態,如何調用?

public string AddText 
    { 
     set 
     { 
      if (listView1.InvokeRequired) 
      { 
       this.Invoke((MethodInvoker)delegate 
       { 
        Textbox.text += value + "\n"; 
       }); 
      } 
      else 
      { 
       Textbox.text += value + "\n"; 
      } 
     } 
    } 

這裏的問題是:

var form = Form.ActiveForm as Form1; 
    if (form != null) 
     form.AddText = "Test"; 

我正在寫一個分析器,其分析數據包。我無法將表格始終放在焦點上,因爲我必須對應用程序執行操作。我正在寫這個分析器以獲取一個數據包,以便我可以分析它。

如果我觸摸應用程序,我想分析Form.ActiveForm返回null。

有沒有一種方法可以調用並設置文本框添加文本,即使表單不在頂部?

回答

2

我認爲問題的根源在於數據包分析器和主表單之間的緊密耦合。數據包分析器不必知道任何關於活動表單的信息,或者甚至根本沒有任何表單。它使事情變得很難維護,因爲它只能在一些非常特殊的情況下工作,而這種情況在一些時候已經不真實。

您可以繞過問題,並從分析數據包的類中引發事件。這給了你更好的封裝,因爲現在分組分析器需要對應用程序的其餘部分一無所知。您可以創建自己的事件參數或重用像System.Diagnostics.DataReceivedEventArgs之類的示例。然後,您的表單可以吸收DataReceived事件並調用其自己的AddText以調用回主線程,無論窗體是否可見,它都將起作用。

至少可以工作,但它是一個阻塞調用,因此數據包分析器線程將被停止,直到表單完全處理該事件並且返回到主線程的編組調用返回。如果運行速率不是很高,那可以,但通常情況下,您不希望阻止通信線程等待主線程更新文本框。另一種方法是使用數據包分析器內的StringBuilder記錄文本,並通過線程安全公共屬性公開它(累積文本,而不是StringBuilder)。或者,如果您需要分開各個消息,則可以將它們添加到列表中,並讓線程安全屬性返回累積消息數組。然後,您的表單可以使用定時器以適合您的應用程序的任何速率輪詢分析器以查找新的記錄數據,並且只有當表單可見時才能輪詢分析器。它不會更新的速度相當快,但對分析器線程的影響幾乎爲零,並且它應該運行得更快,因爲它將StringBuilder或List中的許多消息合併到更新之間,而不是將每個數據包連接到Text屬性。

1

您可以使用工作單元模式爲此與窗體的OnActivation事件。

將'if active form'檢查放在你的AddText方法中。 如果表單未處於活動狀態,請將文本放入列表中以備後用。

然後,處理窗體的OnActivation事件,並且如果列表有值,則將它們推回到AddText。然後,當表單變爲激活狀態(這發生在表單獲得焦點時),文本將被填充。

即使OnActivation部分不起作用,這個通用模式也應該這樣做。

1

如果你不能調用的問題,那麼你的答案是使用SynchronizationContext它始終可用Application.Run線程上。因此,請執行以下操作:

在Form OnLoad將SynchronizationContext.Current保存到任何位置的靜態字段。 之後,您可以在GUI線程中輕鬆使用Post或Send方法進行同步或異步調用。

說明這裏:http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx

尼斯文章在這裏:http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

1

分割問題分爲兩個部分。使用Trace.TraceInformation()記錄文本並實現處理顯示方面的TraceListener。

通過這種方式,您可以簡單地使用配置文件中的條目將日誌輸出重定向到文件,Windows事件日誌或您的UI或任何其他文件。你不必挑一個。如果有幫助,你可以做所有上述事情。

這是一個普通和常見的問題,MSDN示例實現TraceListener正是你所需要的。

相關問題