C# 如何使用基于任务的异步模式(TAP)从FileWatcher事件更新GUI
最近,我开始学习C#,编写了一个简单的应用程序,监视目录并根据写入该目录中文件的行更新表单。在某个时刻,我在尝试从C# 如何使用基于任务的异步模式(TAP)从FileWatcher事件更新GUI,c#,winforms,asynchronous,task,file-watcher,C#,Winforms,Asynchronous,Task,File Watcher,最近,我开始学习C#,编写了一个简单的应用程序,监视目录并根据写入该目录中文件的行更新表单。在某个时刻,我在尝试从FileWatcher事件更新表单元素时遇到了公共invalidooperationexception 我搜索了stackoverflow,似乎在这种情况下我使用了基于任务的异步模式(TAP),但我不知道应该将哪个方法标记为async,以及将哪个方法作为任务启动。关于stackoverflow有很多相关问题,但我发现没有一个问题涵盖了我的应用程序的所有3个方面: 使用FileWat
FileWatcher
事件更新表单元素时遇到了公共invalidooperationexception
我搜索了stackoverflow,似乎在这种情况下我使用了基于任务的异步模式(TAP),但我不知道应该将哪个方法标记为async
,以及将哪个方法作为任务启动。关于stackoverflow有很多相关问题,但我发现没有一个问题涵盖了我的应用程序的所有3个方面:
- 使用
FileWatcher
- 更新
表单
元素
- 使用水龙头
那么,如果我想使用基于任务的异步模式,从FileWatcher触发的事件更新表单元素的最佳实践是什么?还是应该使用另一种模式/另一种应用程序结构
以下是我的应用程序的简化示例:
// 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);
}
}
}
更新21.07:
看来我对使用TAPeverywhere的想法是错误的,因此我最终通过调用包含我的SetSomeVaue
方法的委托来实现这一点,并且它工作正常(我希望这是一个正确的决定)
感谢您的回复 有帮助吗?@user3185569我还没有尝试调用委托,因为根据回答,我似乎应该在.NET 4.5+中使用TAP。我认为您不能将TPL与FileSystemWatcher
一起使用。TAP与FileSystemWatcher是EAP有什么关系。而这两者并不是相互排斥的。您应该为FileWatcher使用EAP,因为使用EAP更好。您可以将任何事件转换为任务,但在这种情况下不应执行。调用和调用同步与EPL的TAP无关。但通常的FSW场景涉及持续监视;这是基于队列的,而不是基于任务的。也许在您的场景中,使用专用线程来消费数据的BlockingCollection
更合适。很难说……问题很广泛。