📄 asyncmessageresponsesink.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 915 $</version>
// </file>
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Collections;
using System.Threading;
namespace CustomSinks
{
class AsyncMessageResponseSink: IMessageSink
{
IMessage msgResponse;
EventWaitHandle responseReceived = new EventWaitHandle(false, EventResetMode.ManualReset, "Waiting for response");
EventWaitHandle messageLoop;
static List<EventWaitHandle> messageLoopsSTA = new List<EventWaitHandle>();
static object storeOneEventLock = new object();
static object invokeEventOnceLock = new object();
static EventForwarderEventArgs storedEvent;
static EventWaitHandle recheckEventStatus = new EventWaitHandle(false, EventResetMode.AutoReset, "Waiting for remoting event to be handled");
static AsyncMessageResponseSink()
{
// We may want to invoke some events ourseves
EventForwarder.EventReceived += new EventForwarderEventHandler(OnEventReceived);
// From now on, OnEventReceived can be called at ANY time; even more times at once!
}
public AsyncMessageResponseSink()
{
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA) {
messageLoop = new EventWaitHandle(false, EventResetMode.AutoReset, "Waiting for message loop to be pumped");
lock (messageLoopsSTA) {
messageLoopsSTA.Add(messageLoop);
}
}
}
public IMessage WaitForResponse()
{
// We are going to invoke events only if we are running on ApartmentState.STA
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA) {
responseReceived.WaitOne();
} else {
// Message loop:
while (true) {
Thread.Sleep(100);
//WaitHandle.WaitAny(new WaitHandle[] {messageLoop, responseReceived});
//responseReceived.WaitOne(100, false);
if (msgResponse != null) break;
System.Windows.Forms.Application.DoEvents();
InvokeStoredEvent();
};
// We have got the response now
lock (messageLoopsSTA) {
messageLoopsSTA.Remove(messageLoop);
}
// We might be the last message loop - this would release the event
recheckEventStatus.Set();
}
return msgResponse;
}
// This function can be called at any time any number of times
void InvokeStoredEvent()
{
lock (invokeEventOnceLock)
{
if (storedEvent != null) {
storedEvent.InvokeEvent();
recheckEventStatus.Set();
}
}
}
// This function can be called at any time any number of times
static void OnEventReceived(object sender, EventForwarderEventArgs args)
{
lock (storeOneEventLock) // Store just one event at a time
{
while ((messageLoopsSTA.Count > 0) && // While there is someone who can invoke us
(args.WasInvoked == false)) // and while the event was not invoked yet
{
// Store event
storedEvent = args;
// Pump all STA message loops
lock (messageLoopsSTA) {
foreach (EventWaitHandle loop in messageLoopsSTA) {
loop.Set();
}
}
// Wait until we are told to check conditions again
recheckEventStatus.WaitOne();
}
}
}
IMessage IMessageSink.SyncProcessMessage(IMessage msg)
{
if (System.Threading.Thread.CurrentThread.Name == null) {
System.Threading.Thread.CurrentThread.Name = "Response thread";
}
Console.WriteLine("Remoting response: " + msg.Properties["__MethodName"]);
msgResponse = msg;
responseReceived.Set();
return msgResponse;
}
IMessageCtrl IMessageSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return null; // Should not be called
}
IMessageSink IMessageSink.NextSink {
get {
return null; // Should not be called
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -