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但问题是为什么它在一个控制台应用程序中工作,而不是在两个控制台应用程序中工作?