0

I'm a complete newbie to WPF/C# and have a project which I'm trying to implement a way to output information to a textbox labelled LogText live from a Process instance. I will detail how I currently have it setup and after, what issues I'm facing:

In MainWindow.xaml.cs just to show the form which works:

    private void Button_Click(object sender, RoutedEventArgs e) {
        xLogger.Instance.Show();
    }

I'm pulling it statically from the LoggerView.xaml.cs:

public static xLogger _Instance;
public static xLogger Instance { get { return _Instance; } set { _Instance = value; } }

I also have a small (probably useless) method for now inside this:

public void AddEntry(string entry) { LogText.AppendText(entry); }

The process I'm running for tests is dism.exe CMD tool with a DataReceivedEventHandler:

public static void Run() {
    Process dProcess = new Process();
    dProcess.StartInfo.FileName = "dism.exe";
    dProcess.StartInfo.Arguments = "/online /cleanup-image /restorehealth";
    dProcess.StartInfo.UseShellExecute = false;
    dProcess.StartInfo.RedirectStandardOutput = true;
    dProcess.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
    dProcess.Start();
    dProcess.BeginOutputReadLine();
}

public static void OutputHandler(object sender, DataReceivedEventArgs e) {
        xLogger.Instance.AddEntry(e.Data);
}

And now if we go back to the MainWindow.xaml.cs

private async void runDismScanButton_Click(object sender, RoutedEventArgs e) {
    await Task.Run(() => Dism.Run());
}

So, this actually all runs just fine. In the OutputHandler method, if I replace the Instance.AddEntry() call to Console.WriteLine() then it works perfect, this was my first test before anything and it seemed to have worked. Now, when I use it as displayed above with Instance.AddEntry() I get the following error

Object reference not set to an instance of an object

Which in this case is self explanatory. So what I did here is define the object inside MainWindow.xaml.cs which when I come to think about it, I'm probably using or interacting with the object inside the UI thread? I found out after some reading that this won't work, and makes sense.

Either way, I did it this way and I get the error:

The calling thread cannot access this object because a different thread owns it

Which confirms that I am probably accessing it on the wrong thread, in this case the UI one, and I've learned I shouldn't do that and should use background workers and be sure to use the new async await features.

When I received that error initially, I started reading about BeginInvoke() in order to do things like this however I don't understand how I'm supposed to use it in this context or how it's supposed to work fully. I've read the documentation, I can't piece it together for this case admittedly.

Finally, my questions are this:

  1. Am I doing this correctly? If I want to update a textbox live with information as a command pushes out the information. Is there a preferable way to do this?
  2. How do I use this xLogger in other classes simultaneously without instantiating an object every time? I know static methods help with this, but again I'm not sure how it's done.
  3. The instance of the logger will always be null until an object is created, so where do I initially create the object to use for reuse? Or am I incorrect?
  4. Is my understanding of this situation wrong in any way?
Xanmashi
  • 157
  • 1
  • 2
  • 10

0 Answers0