CeeRo
CeeRo

Reputation: 1142

Locking richtextboxes called from non-UI thread

Given the following code, how would I be able to lock the richtextbox so that each log-call gets to finish working before another can start typing to it?

private delegate void ReportLogDelegate(RichTextBox box, Color color, string message);

public void FileLog(string file, string project, string type, string fileNr, string note)
{
    if (type == "incoming")
    {
        this.Invoke(new ReportLogDelegate(this.AppendText), new object[] { logTextBox, Color.Orange, String.Format("{0} - {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString()) });
        string message = string.Format("\n\tFile Incoming\n\tFile: {0}\n\tProject: {1}\n\tFileNumber: {2}\n\n", file, project, fileNr);
        this.Invoke(new ReportLogDelegate(this.AppendText), new object[] { logTextBox, Color.White, message });
    }
    else if (type == "done")
    {
        this.Invoke(new ReportLogDelegate(this.AppendText), new object[] { logTextBox, Color.GreenYellow, String.Format("{0} - {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString()) });
        string message = string.Format("\n\tFile Received\n\tFile: {0}\n\tProject: {1}\n\tFileNumber: {2}\n\n", file, project, fileNr);
        this.Invoke(new ReportLogDelegate(this.AppendText), new object[] { logTextBox, Color.White, message });
    }
    else if (type == "error")
    {
        this.Invoke(new ReportLogDelegate(this.AppendText), new object[] { logTextBox, Color.Red, String.Format("{0} - {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString()) });
        string message = string.Format("\n\tError Receiving File\n\tFile: {0}\n\tProject: {1}\n\tFileNumber: {2}\n\tError: {3}\n\n", file, project, fileNr, note);
        this.Invoke(new ReportLogDelegate(this.AppendText), new object[] { logTextBox, Color.Red, message });
    }
}


// Append text of the given color.
void AppendText(RichTextBox box, Color color, string text)
{
    int start = box.TextLength;
    box.AppendText(text);
    int end = box.TextLength;

    // Textbox may transform chars, so (end-start) != text.Length
    box.Select(start, end - start);
    {
        box.SelectionColor = color;
        // could set box.SelectionBackColor, box.SelectionFont too.
    }
    box.SelectionLength = 0; // clear
}

Each call to FileLog should be allowed to run to the end before another has access to the RTB.

Upvotes: 2

Views: 340

Answers (1)

Servy
Servy

Reputation: 203817

Just put the whole body of the method into a lock block. Create a new private object to lock on so that you can be sure no other methods are using that same sync lock:

private object key = new object();
public void FileLog(string file, string project, string type, string fileNr, string note)
{
    lock(key)
    {
        //your existing implementation goes here
    }
}

This is assuming that you don't have any other methods that would also be accessing that rich text box. If you do have others then you'll need to ensure that the object that you lock on is accessible to all of them.

Upvotes: 4

Related Questions