[英]GUI Freezes - Invalid Operation Exception c#
我在c#中有一個GUI,您可以在其中打開日志文件。 該程序具有2個主要功能:setTextMessageTextBox(),可在需要時更新GUI(在每次操作后提供適當的消息)
private static void setTextMessageTextBox(){
MyProject.mainForm update = new MyProject.mainForm();
//messageTextBox.Text is set by default to "Open the file".
const string msg_0 = "Open the file";
const string msg_1 = "Press button to start reading";
const string msg_2 = "Please wait, Reading in progress";
const string msg_3 = "Reading finished";
string textCurrent = update.messageTextBox.Text;
switch (textCurrent){
case msg_0 :
update.messageTextBox.Text = msg_1;
break;
case msg_1 :
update.messageTextBox.Text = msg_2;
break;
case msg_2 :
update.messageTextBox.Text = msg_3;
break;
case msg_3 :
//msg_4 is a global variable with the result
update.messageTextBox.Text = msg_4;
break;
}//switch
}//method setMessageBoxTest
然后,我有完成所有工作的analytics()方法(日志非常大,因此最多需要1分鍾才能完成)。
private void analyze(){
//reading log
//cutting log
//calls other classes to take what pieces are needed
//calls other classes to decode pieces
//saves the final result to msg_4
}
最后,我有按鈕AnalyzeButton觸發:
private void analyzeButton_Click(object sender, EventsArgs e){
setTextMessageTextBox();
analyze();
setTextMessageTextBox();
}//analyzeButton
結果是僅在分析功能完成后,GUI才會凍結,並且文本框將被更新。
我試過了:
MethodInvoker startAnalyze = new MethodInvoker(analyze);
startAnalyze.Invoke();
但是GUI仍然凍結
我試圖調用setTextBox
MethodInvoker setMessage = new MethodInvoker(setMessageTextBox);
setMessage.Invoke();
GUI仍然凍結
我嘗試將兩者與方法調用程序一起使用,但引發了無效操作異常。
最后,我使用begin_invoke而不是Invoke進行分析:
MethodInvoker beginning = new MethodInvoker (analyze);
beginning.BeginInvoke(null, null)
GUI不再凍結,但textBox仍未更新。
我已經閱讀了有關BackgroundWorker的信息,但也許我錯過了一些東西,但根本沒有用。 任何人都有我所缺少的線索,或者是否有更好的解決方法? 感謝您的時間。
更新:@SriramSakthivel我將新實例的創建移到了全局變量級別,但是結果仍然相同。 GUI不會凍結,但不會更新textBox。 在我按下按鈕之前,它已更新。 例如 文本從“打開文件”更改為“ 按下”按鈕以開始閱讀,但是在按下按鈕后,文本框保持原樣。 將新實例設置為全局實例后,我通過兩種方式進行了測試:調用setMessageTextBox,以及在執行適當的操作之前和之后手動分配新消息。 恩。 'update.messageTextBox.Text =“分析”; update.messageTextBox.Refresh(); 分析(); '我嘗試使用和不使用.Refresh(),但仍然沒有任何改變。
首先,在每次調用setTextMessageTextBox()
時都沒有必要為表單創建新實例。 我很確定您不想為每條日志消息彈出一堆窗口(實際上,您甚至沒有顯示這些新表格)。
接下來,必須僅從UI線程更新GUI元素。 如果您要在UI線程上進行長時間運行的操作,並設置不同控件的progress屬性,則在完成作業之前不會重繪它們,因為設置這些屬性(如Text
)只會使它們無效,並且基本上告訴運行時重繪下次UI線程別無它們時。
換句話說,無論是BackgroundWorker
, Task
還是普通Thread
,都必須使用后台工作程序來執行此操作。 然后,此后台線程應調用progress update方法,該方法將確保將update操作調度到UI線程(現在也可以自由地對其進行重新繪制):
class MyForm : Form
{
public void ShowMessage(string msg)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<string>(ShowMessage, msg));
return;
}
this.messageTextBox.Text = msg;
}
}
然后僅從此Form
實例調用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.