【问题标题】:halt in backgroundworker thread when using scintilla NET to not freeze the GUI使用 scintilla NET 不冻结 GUI 时在后台工作线程中停止
【发布时间】:2013-02-11 20:22:11
【问题描述】:

后台工作程序在被调用以将文本附加到闪烁控件时停止,这是部分代码。添加try catch逻辑后,还是没有出现异常!

 private delegate void DWrite(string text);
    private void Write(string text)
    {
        try
        {
            scintilla1.AppendText(text);
        }
        catch (Exception ex) { MessageBox.Show(ex.ToString()); }

    }


    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        string x;
        while (true)
        {
            x = tcw.Read();
           // MessageBox.Show(x);
            Thread.Sleep(100);
            try
            {
                scintilla1.Invoke(new DWrite(Write), x);
            }
            catch (Exception ex) { MessageBox.Show(ex.ToString()); }
        //    scintilla1.Update();
        }

我添加了这个逻辑:

 static void MyHandler(object sender, UnhandledExceptionEventArgs args)
    {
        Exception e = (Exception)args.ExceptionObject;
        MessageBox.Show("MyHandler caught : " + e.Message);
    }

    public void doworkstuff()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
        try
        {
            for (int i = 0; i < 5; i++)
                scintilla1.Invoke(new DWrite(Write), tcw.Read());
        }
        catch (Exception ex)
        { MessageBox.Show(ex.ToString()); }
    }

问题似乎在于它自己的控制,不允许外部线程访问以避免死锁。有没有一种方法可以让我在不使用 BGWorker 的情况下获得相同的功能? tcw.read() 是一个 telnet 客户端,它将输入流式传输到控件,我希望流式传输(即 tcw.read())继续直到用户在表单上按下停止!

【问题讨论】:

  • 启动后台worker的代码在哪里?是否阻塞了等待后台worker的线程?
  • 它在按钮单击方法上调用,该方法写入 scintillaNET 配置文件,然后发出 bw.RunWorkerAsync();
  • 没有异常,backgroundworker不加文字也不重复while循环就返回
  • UI 是冻结的,还是保持响应?
  • 很可能是一个异常被抛出,而你只是没有捕捉到它。将 do work 处理程序包装在 try/catch 中,该程序在某处记录异常详细信息。例如,scintilla1 可能为空。

标签: c# multithreading user-interface backgroundworker scintilla


【解决方案1】:

您在 ScintillaNET 中发现了一个错误。

为了处理托管 Scintilla 包装器和本机 Scintilla 控件之间的互操作,ScintillaNET 重写了 WndProc 方法。这样一来,用于封送回 UI 线程的调用的 Windows 窗体机制似乎已被破坏。

与此同时,您可以使用BackgroundWorker.ProgressChanged 事件来精确地执行您正在尝试的定期 UI 更新类型。

确保您已将 BackgroundWorker.WorkerReportsProgress 属性设置为 true 后,修改您的代码以便使用 BackgroundWorker.ReportProgress 方法代替 Invoke 方法并处理 ProgressChanged 事件。

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    string x;
    while (true)
    {
        x = "Your telnet data";
        Thread.Sleep(100);
        worker.ReportProgress(-1, x);
    }
}

private void bg_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    string text = e.UserState as string;
    scintilla1.AppendText(text);
}

(完全披露:我是一名 ScintillaNET 开发人员)

【讨论】:

    【解决方案2】:

    你应该设置一些中断条件,你的 while 循环是一个无限循环! 如果您使用 BeginInvoke 而不是 Invoke,后台工作人员不会停止!

    scintilla1.BeginInvoke(new DWrite(Write), x);
    

    【讨论】:

    • 不,我试着像这样循环看看这是否是导致问题的原因;整数 = 0; while(i
    • 您是否尝试过简单地调用没有while循环的方法?
    • 没有时间,使用 BeginInvoke,同样的行为!
    • 您可以尝试在 UI 线程上触发的 RunWorkerCompleted 事件中更新 UI。但是我不确定这是否是您所需要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    相关资源
    最近更新 更多