C# 如何在c中等待事件被处理#
假设我们有这样的代码:C# 如何在c中等待事件被处理#,c#,.net,multithreading,events,C#,.net,Multithreading,Events,假设我们有这样的代码: public class MyProcess { private Process _process; public event EventHandler OnFinish; public MyProcess(string pathToExe) { _process = new Process(); _process.StartInfo.FileName = pathToExe; } pub
public class MyProcess
{
private Process _process;
public event EventHandler OnFinish;
public MyProcess(string pathToExe)
{
_process = new Process();
_process.StartInfo.FileName = pathToExe;
}
public int Start()
{
_process.Exited += _processExited;
_process.Start();
return _process.Id;
}
public void Stop()
{
_process.Stop();
}
private void _processExited(object sender, EventArgs e)
{
OnFinish?.Invoke();
}
}
public class MyProgram
{
private static int stoppedProcs = 0;
public static void Main(string[] args)
{
var proc = new MyProcess("foo.exe");
proc.OnFinish += proc_OnFinish;
proc.Start();
proc.Stop();
//Wait here to display 1 instead of 0
Console.WriteLine(stoppedProcs);
}
private static void proc_OnFinish(object sender, EventArgs e)
{
stoppedProcs++;
}
}
我创建并启动流程。然后我想停止它,只有在我处理完事件后才继续。问题是我自己并没有像操作系统那样调用事件。如何理解事件处理程序已完成?假设您希望同步等待(阻止当前线程),只需通过类公开该方法即可 扩展提及
任务
和等待
内容的答案
如果要将等待转换为异步流,可以将退出的事件与TaskCompletionSource
组合,如下所示:
public static class ProcessExtension
{
public static Task WaitForExitAsync(this Process proc, Action callback)
{
return new WaitForExitExt(proc, callback).WaitTask;
}
class WaitForExitExt
{
private TaskCompletionSource<int> _tcs;
private Action _callback;
public WaitForExitExt(Process proc, Action callback)
{
_callback = callback;
proc.EnableRaisingEvents = true;
_tcs = new TaskCompletionSource<int>();
if (proc.HasExited)
{
_tcs.TrySetResult(proc.ExitCode);
}
else
{
proc.Exited += OnProcessExited;
// Process already exited by the time the handler was attached.
if (proc.HasExited)
{
proc.Exited -= OnProcessExited;
_tcs.TrySetResult(proc.ExitCode);
}
}
}
public Task WaitTask => _tcs.Task;
private void OnProcessExited(object sender, EventArgs e)
{
var proc = (Process)sender;
proc.Exited -= OnProcessExited;
_callback();
_tcs.TrySetResult(proc.ExitCode);
}
}
}
输出为:
Exited
Task finished
谢谢大家回答我的问题。
@Fildor建议使用ManualResetEvent
public class MyProgram
{
private static int stoppedProcs = 0;
private static ManualResetEvent mre = new ManualResetEvent(false);
public static void Main(string[] args)
{
var proc = new MyProcess("foo.exe");
proc.OnFinish += proc_OnFinish;
proc.Start();
proc.Stop();
//Wait here to display 1 instead of 0
mre.WaitOne();
mre.Reset();
Console.WriteLine(stoppedProcs);
}
private static void proc_OnFinish(object sender, EventArgs e)
{
stoppedProcs++;
mre.Set();
}
}
是您的过程
类系统.诊断.过程
?我在System.Diagnostics.Process
中未找到任何Stop
。请查看事件模式,或者您是否希望坚持事件模式。不过,您也可以切换到基于任务的异步()。@LouisGo是的。我错了,我用Kill()@LouisGo我不明白我能在这里等待什么。我不调用异步方法。我杀死一个进程,操作系统发出信号,表示进程退出,然后处理程序退出invoked@Alexander抱歉,费尔多的建议更适合您的情况,我将删除我的评论以避免混淆。此解决方案可能很简单,但它是否可靠?如果在mre.WaitOne()
行之前调用中的proc\u OnFinish
处理程序,会发生什么情况?“这能保证永远不会发生吗?”西奥多·祖利亚斯,问得好。据我所知,这并不重要。如果在mre.WaitOne()
之前调用处理程序并调用mre.Set()
则主线程不会被阻止。你说得对,我已经忘记了这一点!因此,如果proc\u OnFinish
只运行一次,则没有竞争条件。行stoppedProcs++
表明情况可能并非如此!顺便说一句,看看线程安全增量的方法。
Exited
Task finished
public class MyProgram
{
private static int stoppedProcs = 0;
private static ManualResetEvent mre = new ManualResetEvent(false);
public static void Main(string[] args)
{
var proc = new MyProcess("foo.exe");
proc.OnFinish += proc_OnFinish;
proc.Start();
proc.Stop();
//Wait here to display 1 instead of 0
mre.WaitOne();
mre.Reset();
Console.WriteLine(stoppedProcs);
}
private static void proc_OnFinish(object sender, EventArgs e)
{
stoppedProcs++;
mre.Set();
}
}