C# 在c中如何阻止直到触发事件#
询问之后,我想知道是否可以等待触发事件,然后获取事件数据并返回部分数据。有点像这样:C# 在c中如何阻止直到触发事件#,c#,events,C#,Events,询问之后,我想知道是否可以等待触发事件,然后获取事件数据并返回部分数据。有点像这样: private event MyEventHandler event; public string ReadLine(){ return event.waitForValue().Message; } ... event("My String"); ...elsewhere... var resp = ReadLine(); ManualResetEvent oSignalEvent = new Manual
private event MyEventHandler event;
public string ReadLine(){ return event.waitForValue().Message; }
...
event("My String");
...elsewhere...
var resp = ReadLine();
ManualResetEvent oSignalEvent = new ManualResetEvent(false);
void SecondThread(){
//DoStuff
oSignalEvent.Set();
}
void Main(){
//DoStuff
//Call second thread
System.Threading.Thread oSecondThread = new System.Threading.Thread(SecondThread);
oSecondThread.Start();
oSignalEvent.WaitOne(); //This thread will block here until the reset event is sent.
oSignalEvent.Reset();
//Do more stuff
}
var foo = new Foo();
ThreadPoolScheduler.Instance
.Schedule(
TimeSpan.FromSeconds(5.0),
() => foo.SendLine("Bar!"));
var resp = foo.ReadLine();
Console.WriteLine(resp);
请确保您提供的任何解决方案都直接返回值,而不是从其他地方获取。我想问的是,上述方法在某种程度上是否可行。我知道Auto/ManuelResetEvent,但我不知道它们是否像上面那样直接返回值
更新:我使用MyEventHandler
(其中包含消息
字段)声明了一个事件。我在另一个名为ReadLine
的线程中有一个方法,正在等待事件触发。当事件激发时,WaitForValue方法(事件处理场景的一部分)返回事件args,其中包含消息。然后,ReadLine将消息返回给任何调用它的对象
我问他我做了什么,但感觉不太对劲。在ManuelResetEvent触发和程序检索并返回数据之间,几乎感觉数据可能发生了什么
更新:自动/手动重置事件的主要问题是它太容易受到攻击。线程可能会等待事件,然后在将其更改为其他内容之前,没有足够的时间让其他人获得它。有没有办法使用锁或其他东西?可能使用get和set语句。您可以使用。在启动次线程之前重置事件,然后使用该方法阻止当前线程。然后,您可以让次线程设置ManualResetEvent,这将导致主线程继续。大概是这样的:
private event MyEventHandler event;
public string ReadLine(){ return event.waitForValue().Message; }
...
event("My String");
...elsewhere...
var resp = ReadLine();
ManualResetEvent oSignalEvent = new ManualResetEvent(false);
void SecondThread(){
//DoStuff
oSignalEvent.Set();
}
void Main(){
//DoStuff
//Call second thread
System.Threading.Thread oSecondThread = new System.Threading.Thread(SecondThread);
oSecondThread.Start();
oSignalEvent.WaitOne(); //This thread will block here until the reset event is sent.
oSignalEvent.Reset();
//Do more stuff
}
var foo = new Foo();
ThreadPoolScheduler.Instance
.Schedule(
TimeSpan.FromSeconds(5.0),
() => foo.SendLine("Bar!"));
var resp = foo.ReadLine();
Console.WriteLine(resp);
您可以等待的一种非常简单的事件是
ManualResetEvent
,更好的是ManualResetEventSlim
他们有一个WaitOne()
方法,可以完全做到这一点。您可以永远等待,或者设置一个超时,或者设置一个“取消令牌”,这是您决定停止等待事件的一种方式(如果您想取消您的工作,或者您的应用程序被要求退出)
您可以通过调用Set()
来触发它们
是文档。如果您乐于使用Microsoft反应式扩展,那么这可以很好地工作:
public class Foo
{
public delegate void MyEventHandler(object source, MessageEventArgs args);
public event MyEventHandler _event;
public string ReadLine()
{
return Observable
.FromEventPattern<MyEventHandler, MessageEventArgs>(
h => this._event += h,
h => this._event -= h)
.Select(ep => ep.EventArgs.Message)
.First();
}
public void SendLine(string message)
{
_event(this, new MessageEventArgs() { Message = message });
}
}
public class MessageEventArgs : EventArgs
{
public string Message;
}
我需要在另一个线程上调用
SendLine
消息以避免锁定,但此代码显示它按预期工作。如果当前方法是异步的,则可以使用TaskCompletionSource。创建事件处理程序和当前方法可以访问的字段
TaskCompletionSource<bool> tcs = null;
private async void Button_Click(object sender, RoutedEventArgs e)
{
tcs = new TaskCompletionSource<bool>();
await tcs.Task;
WelcomeTitle.Text = "Finished work";
}
private void Button_Click2(object sender, RoutedEventArgs e)
{
tcs?.TrySetResult(true);
}
到
while循环怎么样:
while(someGlobalvar)
cahngesomeGlobalvar
在一个函数中,你可以登录到事件。它是活动的等待,这是一个非常糟糕的解决方案,除了这个问题早于那个问题:)@Vahid,自从我问这个问题以来,又有7年的编程经验,我想说,如果你不得不这么做,你可能做错了。最好指定一个回调。如果您使用的是不允许任何其他操作(如COM)的旧系统,则只需让代码等待ManualResetEvent并设置第二个事件以保护写入,直到所有线程都读取完毕。我还建议您签出。这不会直接返回值。我已经在另一个问题上试过了。这不是我想问的吗?但这不会返回任何值。你能编辑qu并添加不同组件及其交互的概述吗?它将帮助我们更好地了解您试图实现的目标,并有望改进设计。您不需要异步来使用TaskCompletionSource这是真的,但是如果您想在不阻塞UI的情况下等待任务,您确实需要它。可以重置TaskCompletionSource吗?@KyleDelaney否。在我的示例中,您将使用新实例替换tcs。您如何使用非按钮单击的事件来进行此操作?是否有一种方法可以调用事件,等待处理程序完成执行,然后在结束时调用TrySetResult(true)?