Question

The background worker halts when invoked to append text to a scintilla Controls, here is the partial code. After adding try catch logic, i still didn't get any exceptions!

 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();
        }

I added this logic:

 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()); }
    }

The problem seems to be with the control it self, not allowing external threads to access to avoid deadlocks. is there a way that i can get the same functionality without having to use BGWorker? the tcw.read() is a telnet client that streams input to the control, i want the streaming (i.e. tcw.read()) to continue until the users presses stop on the form!

Was it helpful?

Solution

You've found a bug in ScintillaNET.

To handle interop between the managed Scintilla wrapper and the native Scintilla control, ScintillaNET overrides the WndProc method. In so doing, it appears the Windows Forms mechanism for marshaling calls back to the UI thread has been broken.

In the meantime, you can use the BackgroundWorker.ProgressChanged event which is there to do precisely the type of periodic UI update you are attempting.

After making sure you've set the BackgroundWorker.WorkerReportsProgress property to true, modify your code so that you use the BackgroundWorker.ReportProgress method in place of your Invoke method and handle the ProgressChanged event.

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);
}

(full disclosure: I'm a ScintillaNET developer)

OTHER TIPS

You should put some breaking condition, your while loop is an infinite one! If you use BeginInvoke instead of Invoke, the background worker wouldn't halt though!

scintilla1.BeginInvoke(new DWrite(Write), x);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top