C# 如果我们从不同的进程运行代码,那么异步和等待代码的行为会有所不同
请容忍我提出这个长问题 情景: 我在根目录上有一个C# 如果我们从不同的进程运行代码,那么异步和等待代码的行为会有所不同,c#,asynchronous,async-await,console-application,filesystemwatcher,C#,Asynchronous,Async Await,Console Application,Filesystemwatcher,请容忍我提出这个长问题 情景: 我在根目录上有一个FileSystemWatcher,它正在监视控制目录中每个控制文件的LastWrite更改。看起来像这样:- 根目录(FileSystemWatcher实例正在监视此根目录) | |-----control-directory\u 0\control文件 \ data-file \ data-file \ da
FileSystemWatcher
,它正在监视控制目录中每个控制文件的LastWrite
更改。看起来像这样:-
根目录(FileSystemWatcher
实例正在监视此根目录)
|
|-----control-directory\u 0\control文件
\ data-file
\ data-file
\ data-file
\ data-file
|-----control-directory\u 1\控制文件
\ data-file
\ data-file
\ data-file
\ data-file
|-----control-directory\u 2\control文件
\ data-file
\ data-file
\ data-file
\ data-file
|-----control-directory\u 3\控制文件
\ data-file
\ data-file
\ data-file
\ data-file
……更相似的结构(但只有一个根目录)
对不起,我的创意画
我所面临的问题是,根目录中可能有许多控制目录(大约200-500个),除了控制目录的控制文件外,我还有一个数据文件(在每个目录中),其中会发生连续写入
我在监视NotifyFilter.LastWrite和Filter=控制文件。
InternalBufferSize
设置为4KB(请不要要求增加此值,由于需要,我不允许修改它和事件以使其为8KB(默认值),并且我不能对每个控制文件使用FileSystemWatcher
,因为它将占用大量宝贵的非分页内存)
我的EventHandler
如下所示
private void OnChange(Object sender, FileSystemEventArgs eventArgs)
{
//result = CPU bound work here
//evaluating result
}
目前,我正在处理300个控制文件。由于在数据文件上发生了大量的写操作,并且有大量的请求来控制文件,所以我的缓冲区经常溢出
然后我想到了一个主意。(async
和wait
使用任务
战斗坦克进行救援)
它工作得很好,我能够处理大量请求(甚至用1000个事件测试,只有4KB的缓冲区)
现在是有趣的部分。我如何测试它
涉及两个实体,一个是写入控件或数据文件,另一个是处理写入控件文件所生成的事件。所以我去创建了一个控制台应用程序,它可以同时做这两件事
static void Main(string[] args)
{
int controlFileCount = Convert.ToInt32(args[0]);
string basePath = args[1];
//CreateFolderStructure(basePath, controlFileCount); for first run.
FileSystemWatcher baseDirectoryWatcher = new FileSystemWatcher();
SetupFileSystemWatcher(baseDirectoryWatcher, basePath);
WriteToControlFilesParallely(basePath, controlFileCount);
Console.Read();
}
public void SetupFileSystemWatcher(FileSystemWatcher baseDirectoryWatcher, string path)
{
//setting properties of the watcher.
baseDirectoryWatcher.NotifyFilter = NotifyFilter.LastWrite;
baseDirectoryWatcher.Filter = "control-file";
baseDirectoryWatcher.InternalBufferSize = 4096;
baseDirectoryWatcher.Path = path;
baseDirectoryWatcher.IncludeSubdirectories = true;
baseDirectoryWatcher.EnableRaisingEvents = true;
}
public void WriteToControlFilesParallely(string basePath, int controlFileCount)
{
Parallel.For(0, controlFileCount, (i) =>
{
string filePath = Helper.GetFilePath(basePath, i);
Helper.WriteData(filePath, "data");
});
}
接下来,我测试了两个控制台应用程序:-
首先,负责并行地将数据写入各种控制文件-(Writer_App)
第二,负责处理事件-(事件处理应用程序)
注意:内核中没有代码更改,但我现在不是在同一个控制台应用程序中编写和处理事件,而是从一个控制台应用程序编写和处理另一个控制台应用程序
因此,我将这两个实体从我的旧控制台应用程序中分离出来(开始模拟实际环境)。现在我通过运行第一个事件处理应用程序开始测试,然后通过运行Writer应用程序写入控制文件,现在情况变得很奇怪,我的应用程序在没有async
和等待
就像我的第一个实现一样
我再次测试了一个控制台应用程序(它同时负责这两项工作),并且运行良好
那么,为什么两个控制台应用程序使async
和wait
(以及Task
)的魔力消失,而一个控制台应用程序却工作得很好呢
它是否与进程间通信有关
我想知道它是否能在生产中使用,因为我将在Web应用程序中使用处理程序代码,并且其他一些进程可以通过网络编写这些文件
最后,我终于明白了这一点,当我使用单控制台应用程序时,我正在运行它的exe(通过cmd),但当我尝试使用两个控制台应用程序时,我正在visual studio内部运行该应用程序(在发布模式下),因此,由于这个原因(visual studio的负载)我遇到了异常,并将其归咎于async
和wait
因此,如果您处理的代码很紧张,请始终从exe运行应用程序。运行的控制台应用程序是否在某个时候设置了表单async/await
依赖于处理同步的SynchronizationContext
。在一个简单的控制台应用程序中有一个合适的吗?@LasseV.Karlsen没有比它更简单的控制台应用程序了。不涉及“UI上下文”。请查看我的答案-async/await在控制台应用程序中的工作方式与在UI应用程序中的工作方式非常不同。@EJoshuaS但问题是为什么它在一个控制台应用程序中工作,而不是在两个控制台应用程序中工作?