C# 在使用信号量LIM时等待触发事件
我可以使用信号量lim来等待偶数触发,如下所示:C# 在使用信号量LIM时等待触发事件,c#,semaphore,C#,Semaphore,我可以使用信号量lim来等待偶数触发,如下所示: public class MyClass { private SemaphoreSlim _signal; private ObjectThatHasEvent _object; public MyClass() { _signal = new SemaphoreSlim(0, 1); _object = new ObjectThatHasEvent(); _obj
public class MyClass
{
private SemaphoreSlim _signal;
private ObjectThatHasEvent _object;
public MyClass()
{
_signal = new SemaphoreSlim(0, 1);
_object = new ObjectThatHasEvent();
_object.OnEventFired += _object_OneEventFired;
}
public asnyc void Run()
{
_object.DoStuffAndFireEventAfterwards();
_signal.WaitAsync();
}
private void _object_OnEventFired(object sender, EventArgs e)
{
_signal.Release();
}
}
但是,如果我需要先等待来自_对象的事件完成,然后再等待另一个事件,然后再调用_signal.Release,该怎么办?像这样:
public class MyClass
{
private SemaphoreSlim _signal;
private ObjectThatHasEvent _object;
public MyClass()
{
_signal = new SemaphoreSlim(0, 1);
_object = new ObjectThatHasEvent();
_object.OnConnected += _object_OnConnected;
_object.OnWorkFinished += _object_OnWorkFinished;
_object.OnDisconnected += _object_OnDisconnected;
}
public async Task Run()
{
_object.Connect();
await _signal.WaitAsync();
}
private void _object_OnConnected(object sender, EventArgs e)
{
_object.DoWork();
//How to wait for work finished here?
_object.Disconnect();
}
private void _object_OnWorkFinished(object sender, EventArgs e)
{
//Only disconnect after this has finished...
}
private void _object_OnDisconnected(object sender, EventArgs e)
{
_signal.Release();
}
}
根据我的评论,你喜欢这项工作吗
public class MyClass
{
private SemaphoreSlim _signal;
private ObjectThatHasEvent _object;
public MyClass()
{
_signal = new SemaphoreSlim(2, 2);
_object = new ObjectThatHasEvent();
_object.OnConnected += _object_OnConnected;
_object.OnWorkFinished += _object_OnWorkFinished;
_object.OnDisconnected += _object_OnDisconnected;
}
public async Task Run()
{
if (_signal.CurrentCount == 2) // Make sure no other connections exist (still 2 threads available)
{
await _signal.WaitAsync();
_object.Connect();
}
}
private void _object_OnConnected(object sender, EventArgs e)
{
if (_signal.CurrentCount == 1) //Only do work if we've connected
{
await _signal.WaitAsync();
_object.DoWork();
_object.Disconnect();
}
}
private void _object_OnWorkFinished(object sender, EventArgs e)
{
_signal.Release();
}
private void _object_OnDisconnected(object sender, EventArgs e)
{
_signal.Release();
}
}
使用信号量lim作为信号是可能的,但是需要使事件异步友好,即点击。一旦有了异步友好的方法,就可以更自然地组合它们
我更喜欢将TAP包装器作为扩展方法编写,例如:
public static class ObjectThatHasEventExtensions
{
public static Task ConnectAsync(this ObjectThatHasEvent self)
{
// TODO: this wrapper does not handle connection errors.
var tcs = new TaskCompletionSource<object>();
EventHandler handler = null;
handler = (sender, args) =>
{
self.OnConnected -= handler;
tcs.TrySetResult(null);
};
self.OnConnected += handler;
self.Connect();
return tcs.Task;
}
public static Task DoWorkAsync(this ObjectThatHasEvent self)
{
// TODO: this wrapper does not handle work errors.
var tcs = new TaskCompletionSource<object>();
EventHandler handler = null;
handler = (sender, args) =>
{
self.OnWorkFinished -= handler;
tcs.TrySetResult(null);
};
self.OnWorkFinished += handler;
self.DoWork();
return tcs.Task;
}
// (same pattern for DisconnectAsync)
}
你能创建另一个信号量吗?或者允许信号灯上有两个线程而不是一个线程,并使用CurrentCount确保信号灯在正确的位置等待?因此,在运行中,确保等待前_signal.CurrentCount==0,在_object_OnConnectedobject sender中,EventArgs e检查_signal.CurrentCount==1,然后再次等待,然后在_object_OnWorkFinishedobject sender、EventArgs e和_objectondisconnectedobject sender中释放,EventArgs eFYI,事件的名称不以On开头。例如,按钮将有一个单击事件,而不是OnClick事件。当您看到OnClick方法时,它们通常是一个受保护的void方法,类用于引发Click事件。这似乎不起作用。线程永远不会超过第二个等待句柄,并且永远不会调用_object_OnWorkFinished。请参阅更新,我认为您需要将_signal.WaitAsync移到dowork上方。等待之后,您需要执行受信号量保护的工作。
public class MyClass
{
private ObjectThatHasEvent _object;
public MyClass()
{
_object = new ObjectThatHasEvent();
}
public async Task Run()
{
await _object.ConnectAsync();
await _object.DoWorkAsync();
await _object.DisconnectAsync();
}
}