繁体   English   中英

GUI冻结-无效的操作异常c#

[英]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
}

最后,我有按钮Anal​​yzeButton触发:

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线程别无它们时。

换句话说,无论是BackgroundWorkerTask还是普通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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM