I am aware that there are plenty questions have been already asked on this. But the solutions provided about delegates is not what I am getting to work with my code because I am working on 4.5 version and looks like the Dispatcher methods have slightly changed. Added to that, I am touching dotnet nearly after a decade and c# for the first time.
What I am actually tying to do in my WPF project is to append text of the textbox inside the main window to display the status/log. This is inside the singleton class called Logger
The main static function of this class is log() which accepts a string which needs to be added to the text box with one simple line
txt.AppendText(msg);
After doing some research I changed it to
Dispatcher.CurrentDispatcher.Invoke(() =>
{
txt.AppendText(msg);
});
But I still get the same error. What is going wrong here? Is there anything else to do? Because I am calling this Logger.log()
from FileSystemEventHandler
insider another singleton class.
private void somethingChanged(object sender, FileSystemEventArgs e)
{
Logger.log("File: " + e.FullPath + " " + e.ChangeType);
}
Below is my Logger
class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Threading;
namespace httpclientui.comps
{
class Logger
{
private static TextBox txt;
private Logger() { }
public static void setup(TextBox t){
txt = t;
}
public static void clear()
{
if (txt == null)
{
return;
}
txt.Clear();
}
public static void log(String msg, bool addNewLineChar = true)
{
if (txt == null)
{
return;
}
Dispatcher.CurrentDispatcher.Invoke(() => {
txt.AppendText(msg);
});
}
}
}
This is my main window with only one textbox control called txtMessage.
public partial class MainWindow : Window
{
private String folderToWatch;
public MainWindow()
{
InitializeComponent();
initialize();
}
private void initialize()
{
Logger.setup(txtMessage);
Logger.clear();
Logger.log("Launched");
folderToWatch = "E:\\folder\\subfolder";
Watcher.Instance.setup(folderToWatch);
Watcher.Instance.start();
}
}
}
Below is my Watcher class which has FileSystemWatcher object to keep watching one of the folder and whenever something happens inside that folder like adding/deleting files and renaming the files will needs to be logged inside that textbox.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace httpclientui.comps
{
class Watcher
{
private String path;
//https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx
private FileSystemWatcher dog;
private static Watcher instance;
private Watcher()
{
//dog = new FileSystemWatcher()
}
public static Watcher Instance
{
get
{
if (instance == null)
{
instance = new Watcher();
}
return instance;
}
}
public void setup(String folderPath)
{
path = folderPath;
dog = new FileSystemWatcher(folderPath);
Logger.log("setting up to watch folder: " + folderPath);
dog.Changed += new FileSystemEventHandler(somethingChanged);
dog.Created += new FileSystemEventHandler(somethingChanged);
dog.Deleted += new FileSystemEventHandler(somethingChanged);
dog.Renamed += new RenamedEventHandler(somethingRenamed);
}
public void start()
{
Logger.log("starting to watch folder");
dog.EnableRaisingEvents = true;
}
public void pause()
{
dog.EnableRaisingEvents = false;
}
public void stop()
{
dog.EnableRaisingEvents = false;
}
private void somethingChanged(object sender, FileSystemEventArgs e)
{
Logger.log("File: " + e.FullPath + " " + e.ChangeType);
}
private void somethingRenamed(object sender, RenamedEventArgs e)
{
Logger.log("File: " + e.OldFullPath + " renamed to " + e.FullPath);
}
}
}
At first glance, it looks like you are not marshalling the Clear()
method call to the Dispatcher. That's what is likely throwing the exception- all access to DispatcherObjects (which includes all Controls) must be done by the Dispatcher thread.
Also, you want to use Application.Current.Dispatcher
, not Dispatcher.CurrentDispatcher
. The latter just spins up a new Dispatcher on the current (background) thread, which is not what you want.