如果我们 运行 来自不同进程的 async 和 await 代码表现不同
async and await code behaving differently if we run it from different processes
这个问题很长,请耐心等待。
场景:
我在 root-directory 上有一个 FileSystemWatcher
正在监视 LastWrite
在 control-file 上的每个变化控制目录。看起来像这样:-
root-directory (FileSystemWatcher
instance is watching this root directory)
|
|-----control-directory_0 \ control-file
\ data-file
|-----control-directory_1 \ control-file
\ data-file
|-----control-directory_2 \ control-file
\ data-file
|-----control-directory_3 \ control-file
\ data-file
.........more similar structure (but only one root-directory)
对不起我的创意画。
我遇到的问题,根目录里面可以有很多控制目录(大约200-500)和连同 control-directory 的 control-file,我在其中有一个 data-file(在每个其中)发生连续写入的地方。
我在看 NotifyFilter.LastWrite
和 Filter = control-file
。
InternalBufferSize
设置为 4KB(请不要要求增加它,由于要求,我不允许修改它和事件使其成为 8KB(默认值),我不能使用 FileSystemWatcher
对于每个 control-file 因为它会占用大量宝贵的非分页内存)。
我的 EventHandler
看起来像这样
private void OnChange(Object sender, FileSystemEventArgs eventArgs)
{
//result = CPU bound work here
//evaluating result
}
目前,我正在处理 300 个 control-files。由于 data-file 上发生了大量写入,并且 control-file 上有大量请求,我的缓冲区经常溢出。
然后我想到了一个主意。 (async
和 await
使用 Task
主战坦克进行救援)
async private void OnChange(Object sender, FileSystemEventArgs eventArgs)
{
var result = await Task.Run(() => Work.CPUboundWork());
//evaluating result
}
它运行良好,我能够处理大量请求(甚至在只有 4KB 缓冲区的情况下测试了 1000 个事件)。
有趣的部分来了。我如何测试它?
涉及两个实体,一是写入 control 或 data-file,二是处理由写入 控制文件 。所以我上去创建了一个控制台应用程序,它完成了这两件事。
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).
二、负责处理事件-(Event_Handling_App).
注意:核心中没有代码更改,但现在我不是在同一个控制台应用程序中编写和处理事件,而是从一个控制台应用程序编写并处理另一个。
所以我将两个 entities 从我的旧控制台应用程序中分离出来(开始对实际环境进行模拟)。现在我先通过 运行 Event_Handling_App 开始测试,然后通过 运行 写入 control-file Writer_App 现在事情变得很奇怪,我的应用程序面临 InternalBufferOverflow
相同数量的 control-files 异常] 以及当我没有 async
和 await
时与我的第一个实现中相同的写入次数。
我再次使用一个控制台应用程序(它同时承担了这两种责任)进行了测试,它运行良好。
So, why two console applications make the magic of async
and await
(along with Task
) disappear while one console application is working great?
Is it something related to Inter Process Communication?
I am wondering if it will work in production because I will be using handler code in a Web application and some other process can write these files over the network.
最后,我能够弄清楚这一点,当我使用单个控制台应用程序时,我 运行 正在使用它的 exe(通过 cmd),但是当我尝试使用两个控制台应用程序时,我是 运行在 visual studio 中安装应用程序(在发布模式下)所以由于这个(负载为 visual studio)我得到了异常,我责怪 async
和 await
.
因此,如果您正在处理紧凑的代码,请始终 运行 您的应用程序来自 exe。
这个问题很长,请耐心等待。
场景:
我在 root-directory 上有一个 FileSystemWatcher
正在监视 LastWrite
在 control-file 上的每个变化控制目录。看起来像这样:-
root-directory (
FileSystemWatcher
instance is watching this root directory)|
|-----control-directory_0 \ control-file
\ data-file
|-----control-directory_1 \ control-file
\ data-file
|-----control-directory_2 \ control-file
\ data-file
|-----control-directory_3 \ control-file
\ data-file
.........more similar structure (but only one root-directory)
对不起我的创意画。
我遇到的问题,根目录里面可以有很多控制目录(大约200-500)和连同 control-directory 的 control-file,我在其中有一个 data-file(在每个其中)发生连续写入的地方。
我在看 NotifyFilter.LastWrite
和 Filter = control-file
。
InternalBufferSize
设置为 4KB(请不要要求增加它,由于要求,我不允许修改它和事件使其成为 8KB(默认值),我不能使用 FileSystemWatcher
对于每个 control-file 因为它会占用大量宝贵的非分页内存)。
我的 EventHandler
看起来像这样
private void OnChange(Object sender, FileSystemEventArgs eventArgs)
{
//result = CPU bound work here
//evaluating result
}
目前,我正在处理 300 个 control-files。由于 data-file 上发生了大量写入,并且 control-file 上有大量请求,我的缓冲区经常溢出。
然后我想到了一个主意。 (async
和 await
使用 Task
主战坦克进行救援)
async private void OnChange(Object sender, FileSystemEventArgs eventArgs)
{
var result = await Task.Run(() => Work.CPUboundWork());
//evaluating result
}
它运行良好,我能够处理大量请求(甚至在只有 4KB 缓冲区的情况下测试了 1000 个事件)。
有趣的部分来了。我如何测试它?
涉及两个实体,一是写入 control 或 data-file,二是处理由写入 控制文件 。所以我上去创建了一个控制台应用程序,它完成了这两件事。
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).
二、负责处理事件-(Event_Handling_App).
注意:核心中没有代码更改,但现在我不是在同一个控制台应用程序中编写和处理事件,而是从一个控制台应用程序编写并处理另一个。
所以我将两个 entities 从我的旧控制台应用程序中分离出来(开始对实际环境进行模拟)。现在我先通过 运行 Event_Handling_App 开始测试,然后通过 运行 写入 control-file Writer_App 现在事情变得很奇怪,我的应用程序面临 InternalBufferOverflow
相同数量的 control-files 异常] 以及当我没有 async
和 await
时与我的第一个实现中相同的写入次数。
我再次使用一个控制台应用程序(它同时承担了这两种责任)进行了测试,它运行良好。
So, why two console applications make the magic of
async
andawait
(along withTask
) disappear while one console application is working great?Is it something related to Inter Process Communication?
I am wondering if it will work in production because I will be using handler code in a Web application and some other process can write these files over the network.
最后,我能够弄清楚这一点,当我使用单个控制台应用程序时,我 运行 正在使用它的 exe(通过 cmd),但是当我尝试使用两个控制台应用程序时,我是 运行在 visual studio 中安装应用程序(在发布模式下)所以由于这个(负载为 visual studio)我得到了异常,我责怪 async
和 await
.
因此,如果您正在处理紧凑的代码,请始终 运行 您的应用程序来自 exe。