Task.Run( asnyc () => ) Blocking/Not 运行 所有任务 C#
Task.Run( asnyc () => ) Blocking/Not Running All Tasks C#
问题是我尝试 运行 RunPrivateMethod() 多次,但我 运行 遇到阻塞问题,或者当我使用 [=29= 时直接无法工作].与其在这里分享每一次尝试,我只是把我当前的版本。
在 RunPrivateMethod() 中,exeProcess.WaitForExit() 方法是一个外部程序,基本上是 reads/writes/crunches/outputs 数据。我试图 运行 这是一个异步任务,但没有成功。
我不知道这是否合理,但我想限制一次启动的任务数量,所以我在每个案例块的末尾添加了 Task.WaitAll() 。案例 (1) 和案例 (2) 总是都会得到 运行.
所以,这是我的代码。目前,它会在加载每个任务时阻塞。然后似乎只有最后一个任务运行。如果我取出所有任务语句并且 运行 一切正常,它会正常工作。
我真的很感激任何意见或帮助。我的大部分测试最终都会锁定我的系统和键盘。
public void RunSomeTasks(int group)
{
switch (group)
{
case (1):
{
Task.Run(async () => await RunAsyncMethod(param1, param1, group));
Task.Run(async () => await RunAsyncMethod(param1, param2, group));
Task.Run(async () => await RunAsyncMethod(param1, param3, group));
Task.WaitAll();
break;
}
case (2):
{
Task.Run(async () => await RunAsyncMethod(param2, param1, group));
Task.Run(async () => await RunAsyncMethod(param2, param2, group));
Task.Run(async () => await RunAsyncMethod(param2, param3, group));
Task.WaitAll();
break;
}
}
}
async Task RunAsyncMethod(string var1, string var2, string varGroup)
{
////////////////////////////////////////////
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "SomeOutsideEXE";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = var1 + " " + var2 + " " + varGroup;
using (Process exeProcess = Process.Start(startInfo))
{
// did not work -> Task.Run(() => exeProcess.WaitForExit()).Wait();
exeProcess.WaitForExit();
}
}
}
我在这方面工作了无数个小时并阅读了 Cleary 的书,这个最新修订版是这个 post 的一个版本: 目前的结果是每组中的最后一个任务虽然 exeProcess 有效启动时间正确。 运行ning 时我无法使用键盘。
我显然尝试了 RunSomeTasks() 的直接异步方法,然后只是先等待 RunAsyncMethod。我真的需要一些帮助,是的,我已经知道,尽管经过长时间的阅读和反复试验,我也不知道自己到底在做什么。
我稍微修改了您的示例,这应该可以防止 UI 锁定。请注意,我在单击按钮时添加了 async
。还使用 WhenAll 并传入启动的任务,而不是使用 WaitAll。 (针对完全异步模式进行了更新)
private async void button1_Click(object sender, EventArgs e)
{
try
{
await RunSomeTasks(1);
await RunSomeTasks(2);
lblStatus.Text = "done!";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public async Task RunSomeTasks(int group)
{
switch (group)
{
case (1):
{
var t1 = RunMethodAsync(param1, param1, group);
var t2 = RunMethodAsync(param1, param2, group);
var t3 = RunMethodAsync(param1, param3, group);
await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
break;
}
case (2):
{
var t1 = RunMethodAsync(param2, param1, group);
var t2 = RunMethodAsync(param2, param2, group);
var t3 = RunMethodAsync(param2, param3, group);
await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
break;
}
}
}
async Task RunMethodAsync(string var1, string var2, int varGroup)
{
////////////////////////////////////////////
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "SomeOutsideEXE";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = var1 + " " + var2 + " " + varGroup;
using (Process exeProcess = new Process())
{
var cts = new TaskCompletionSource<int>();
exeProcess.StartInfo = startInfo;
exeProcess.EnableRaisingEvents = true;
exeProcess.Exited += (sender, e) =>
{
try
{
cts.SetResult(exeProcess.ExitCode);
}
catch (Exception ex)
{
cts.SetException(ex);
}
};
exeProcess.Start();
await cts.Task.ConfigureAwait(false);
}
}
我想出的最干净的方法来做一个 await
Process.WaitForExit
是这样的,保存订阅 events
等
private async Task RunRubyScript(string filePath)
{
await Task.Run(() =>
{
using (var proc = new Process())
{
var startInfo = new ProcessStartInfo(@"ruby");
startInfo.Arguments = filePath;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
proc.StartInfo = startInfo;
proc.Start();
proc.WaitForExit();
}
});
}
这是 运行 一个 ruby
脚本,但很明显 ProcessStartInfo
相应地修改您的内容以满足您的要求。
希望对您有所帮助!
问题是我尝试 运行 RunPrivateMethod() 多次,但我 运行 遇到阻塞问题,或者当我使用 [=29= 时直接无法工作].与其在这里分享每一次尝试,我只是把我当前的版本。
在 RunPrivateMethod() 中,exeProcess.WaitForExit() 方法是一个外部程序,基本上是 reads/writes/crunches/outputs 数据。我试图 运行 这是一个异步任务,但没有成功。
我不知道这是否合理,但我想限制一次启动的任务数量,所以我在每个案例块的末尾添加了 Task.WaitAll() 。案例 (1) 和案例 (2) 总是都会得到 运行.
所以,这是我的代码。目前,它会在加载每个任务时阻塞。然后似乎只有最后一个任务运行。如果我取出所有任务语句并且 运行 一切正常,它会正常工作。
我真的很感激任何意见或帮助。我的大部分测试最终都会锁定我的系统和键盘。
public void RunSomeTasks(int group)
{
switch (group)
{
case (1):
{
Task.Run(async () => await RunAsyncMethod(param1, param1, group));
Task.Run(async () => await RunAsyncMethod(param1, param2, group));
Task.Run(async () => await RunAsyncMethod(param1, param3, group));
Task.WaitAll();
break;
}
case (2):
{
Task.Run(async () => await RunAsyncMethod(param2, param1, group));
Task.Run(async () => await RunAsyncMethod(param2, param2, group));
Task.Run(async () => await RunAsyncMethod(param2, param3, group));
Task.WaitAll();
break;
}
}
}
async Task RunAsyncMethod(string var1, string var2, string varGroup)
{
////////////////////////////////////////////
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "SomeOutsideEXE";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = var1 + " " + var2 + " " + varGroup;
using (Process exeProcess = Process.Start(startInfo))
{
// did not work -> Task.Run(() => exeProcess.WaitForExit()).Wait();
exeProcess.WaitForExit();
}
}
}
我在这方面工作了无数个小时并阅读了 Cleary 的书,这个最新修订版是这个 post 的一个版本:
我显然尝试了 RunSomeTasks() 的直接异步方法,然后只是先等待 RunAsyncMethod。我真的需要一些帮助,是的,我已经知道,尽管经过长时间的阅读和反复试验,我也不知道自己到底在做什么。
我稍微修改了您的示例,这应该可以防止 UI 锁定。请注意,我在单击按钮时添加了 async
。还使用 WhenAll 并传入启动的任务,而不是使用 WaitAll。 (针对完全异步模式进行了更新)
private async void button1_Click(object sender, EventArgs e)
{
try
{
await RunSomeTasks(1);
await RunSomeTasks(2);
lblStatus.Text = "done!";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public async Task RunSomeTasks(int group)
{
switch (group)
{
case (1):
{
var t1 = RunMethodAsync(param1, param1, group);
var t2 = RunMethodAsync(param1, param2, group);
var t3 = RunMethodAsync(param1, param3, group);
await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
break;
}
case (2):
{
var t1 = RunMethodAsync(param2, param1, group);
var t2 = RunMethodAsync(param2, param2, group);
var t3 = RunMethodAsync(param2, param3, group);
await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
break;
}
}
}
async Task RunMethodAsync(string var1, string var2, int varGroup)
{
////////////////////////////////////////////
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "SomeOutsideEXE";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = var1 + " " + var2 + " " + varGroup;
using (Process exeProcess = new Process())
{
var cts = new TaskCompletionSource<int>();
exeProcess.StartInfo = startInfo;
exeProcess.EnableRaisingEvents = true;
exeProcess.Exited += (sender, e) =>
{
try
{
cts.SetResult(exeProcess.ExitCode);
}
catch (Exception ex)
{
cts.SetException(ex);
}
};
exeProcess.Start();
await cts.Task.ConfigureAwait(false);
}
}
我想出的最干净的方法来做一个 await
Process.WaitForExit
是这样的,保存订阅 events
等
private async Task RunRubyScript(string filePath)
{
await Task.Run(() =>
{
using (var proc = new Process())
{
var startInfo = new ProcessStartInfo(@"ruby");
startInfo.Arguments = filePath;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
proc.StartInfo = startInfo;
proc.Start();
proc.WaitForExit();
}
});
}
这是 运行 一个 ruby
脚本,但很明显 ProcessStartInfo
相应地修改您的内容以满足您的要求。
希望对您有所帮助!