C#에서 이벤트가 발생할 때까지 차단하는 방법
이 질문을 한 후 이벤트가 발생하기를 기다렸다가 이벤트 데이터를 가져와서 그 일부를 반환할 수 있는지 궁금합니다. 다음과 같은 종류:
private event MyEventHandler event;
public string ReadLine(){ return event.waitForValue().Message; }
...
event("My String");
...elsewhere...
var resp = ReadLine();
제공하는 솔루션이 다른 것에서 값을 가져오는 대신 직접 값을 반환하는지 확인하십시오. 위의 방법이 어떤 식 으로든 사용할 수 있는지 묻습니다. Auto/ManuelResetEvent에 대해 알고 있지만 위에서 했던 것처럼 직접 값을 반환하는지 모르겠습니다.
업데이트:MyEventHandler ( Message필드 가 포함된 ) 이벤트를 선언했습니다 . ReadLine이벤트가 발생하기를 기다리는 다른 스레드에 메서드가 있습니다. 이벤트가 발생하면 WaitForValue 메서드(이벤트 처리 장면의 일부)는 메시지가 포함된 이벤트 인수를 반환합니다. 그런 다음 메시지는 ReadLine에 의해 호출된 모든 항목으로 반환됩니다.
허용 대답 에 그 질문에 내가 물었다 내가 무슨 짓을했지만, 그냥 아주 느낌이 좋지 않습니다. ManuelResetEvent 실행과 프로그램이 데이터를 검색하고 반환하는 사이에 데이터에 무슨 일이 일어날 수 있는 것처럼 느껴집니다.
업데이트: 주요 문제 Auto/ManualResetEvent는 너무 취약하다는 것입니다. 스레드는 이벤트를 기다렸다가 다른 이벤트로 변경하기 전에 다른 사람이 이벤트를 얻을 수 있도록 충분한 시간을 주지 않을 수 있습니다. 잠금이나 다른 것을 사용하는 방법이 있습니까? get 및 set 문을 사용할 수 있습니다.
ManualResetEvent 를 사용할 수 있습니다 . 보조 스레드를 실행하기 전에 이벤트를 재설정한 다음 WaitOne() 메서드를 사용하여 현재 스레드를 차단합니다. 그런 다음 보조 스레드에서 기본 스레드가 계속되도록 하는 ManualResetEvent를 설정할 수 있습니다. 이 같은:
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
}
현재 메서드가 비동기인 경우 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);
}
이 예에서는 WelcomeTitle이라는 텍스트 블록과 두 개의 버튼이 있는 양식을 사용합니다. 첫 번째 버튼을 클릭하면 클릭 이벤트가 시작되지만 대기 줄에서 멈춥니다. 두 번째 버튼을 클릭하면 작업이 완료되고 WelcomeTitle 텍스트가 업데이트됩니다. 시간 초과를 원하면 변경하십시오.
await tcs.Task;
에게
await Task.WhenAny(tcs.Task, Task.Delay(25000));
if (tcs.Task.IsCompleted)
WelcomeTitle.Text = "Task Completed";
else
WelcomeTitle.Text = "Task Timed Out";
당신이 기다릴 수 있는 아주 쉬운 종류의 이벤트는 ManualResetEvent, 그리고 더 좋은 것은 ManualResetEventSlim.
그들은 WaitOne()정확히 그것을 수행 하는 방법을 가지고 있습니다 . 영원히 기다리거나 시간 제한을 설정하거나 이벤트 대기를 중단하기로 결정하는 "취소 토큰"을 설정할 수 있습니다(작업을 취소하거나 앱을 종료하라는 메시지가 표시되는 경우).
당신 은 전화 를 해고 Set().
여기 문서가 있습니다.
Microsoft Reactive Extensions를 사용하게 된다면 다음과 같이 잘 작동할 수 있습니다.
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;
}
I can use it like this:
var foo = new Foo();
ThreadPoolScheduler.Instance
.Schedule(
TimeSpan.FromSeconds(5.0),
() => foo.SendLine("Bar!"));
var resp = foo.ReadLine();
Console.WriteLine(resp);
I needed to call the SendLine message on a different thread to avoid locking, but this code shows that it works as expected.
ReferenceURL : https://stackoverflow.com/questions/12745848/how-to-block-until-an-event-is-fired-in-c-sharp
'IT이야기' 카테고리의 다른 글
| Entity Framework에서 모든 엔터티 삭제 (0) | 2021.10.28 |
|---|---|
| Java: 새 키워드와 인터페이스 어떻게 그게 가능합니까? (0) | 2021.10.28 |
| C# 코드용 html 문서 만들기 (0) | 2021.10.27 |
| Typescript- tsconfig의 대상 (0) | 2021.10.27 |
| DIV 대 테이블 또는 CSS (0) | 2021.10.27 |