Recently I started learning C# by writing a simple application that watches directory and updates form based on lines written to file in that directory. At some point I was stuck with common InvalidOperationException
while trying to update form element from FileWatcher
event.
I've searched stackoverflow, and it seems that I should use Task-based Asynchronous Pattern (TAP) in such situations, but I can't figure out which method I should flag as async
, and which to start as a Task
. There are many related questions on stackoverflow, but none I've found cover all 3 aspects of my application:
- Using
FileWatcher
- Updating
Form
element - Using TAP
So, what is the best practice to update Form elements from events, fired by FileWatcher if I want to use Task-based Asynchronous Pattern? Or should I use another pattern / another application structure?
Here is a simplified example of my app:
// Form
public partial class FormMain : Form, IDisplayInterface
{
private CoreClass coreClass;
public void SetSomeVaue(string value)
{
label.Text = value;
}
public FormMain()
{
coreClass = new CoreClass();
coreClass.StartFileWatcher();
}
private void FormMain_Shown(object sender, EventArgs e)
{
coreClass.DisplayInterface = this;
}
}
// Interface
interface IDisplayInterface
{
void SetSomeVaue(string value);
}
// CoreClass
class CoreClass
{
public IDisplayInterface DisplayInterface;
public void StartFileWatcher()
{
FileSystemWatcher watcher = new FileSystemWatcher("C:\Some\Folder")
{
NotifyFilter = NotifyFilters.Size
};
watcher.Changed += new FileSystemEventHandler(FileUpdated);
watcher.EnableRaisingEvents = true;
}
private void FileUpdated(object source, FileSystemEventArgs e)
{
ParseFile(Path.Combine("C:\Some\Folder", e.Name));
}
private void ParseFile(string File)
{
// foreach (var line in newFileLines)
ParseNewRecord(line);
}
private void ParseNewRecord(string line)
{
if (someCondition && DisplayInterface != null)
{
// This triggers Exception for accessing FormMain from a thread that did not create it
DisplayInterface.SetSomeValue(someValue);
}
}
}
UPDATE 21.07:
It looks that I got the wrong idea about using TAP everywhere, so I finally did it by invoking a delegate containing my SetSomeVaue
method and it works correctly (I hope that is a correct decision).
Thanks for response!