ゲーム内のコンソールをWCFインターフェイスに接続して、外部アプリケーションがコンソールコマンドを送信したり、コンソール出力を受信したりできるように遊んでいます。これを達成するために、私は次のサービス契約を作成しました。
public interface IConsoleNetworkCallbacks
{
[OperationContract(IsOneWay = true)]
void NewOutput(IEnumerable<string> text, string category);
}
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IConsoleNetworkCallbacks))]
public interface IConsoleInterface
{
[OperationContract]
void ProcessInput(string input);
[OperationContract]
void ChangeCategory(string category);
}
サーバー上で私はそれを実装しました:
public class ConsoleNetworkInterface : IConsoleInterface, IDisposable
{
public ConsoleNetworkInterface()
{
ConsoleManager.Instance.RegisterOutputUpdateHandler(OutputHandler);
}
public void Dispose()
{
ConsoleManager.Instance.UnregisterOutputHandler(OutputHandler);
}
public void ProcessInput(string input)
{
ConsoleManager.Instance.ProcessInput(input);
}
public void ChangeCategory(string category)
{
ConsoleManager.Instance.UnregisterOutputHandler(OutputHandler);
ConsoleManager.Instance.RegisterOutputUpdateHandler(OutputHandler, category);
}
protected void OutputHandler(IEnumerable<string> text, string category)
{
var callbacks = OperationContext.Current.GetCallbackChannel<IConsoleNetworkCallbacks>();
callbacks.NewOutput(text, category);
}
}
クライアントで、コールバックを次のように実装しました。
public class Callbacks : IConsoleNetworkCallbacks
{
public void NewOutput(IEnumerable<string> text, string category)
{
MessageBox.Show(string.Format("{0} lines received for '{1}' category", text.Count(), category));
}
}
最後に、次のクラスでサービスホストを確立します。
public class ConsoleServiceHost : IDisposable
{
protected ServiceHost _host;
public ConsoleServiceHost()
{
_host = new ServiceHost(typeof(ConsoleNetworkInterface), new Uri[] { new Uri("net.pipe://localhost") });
_host.AddServiceEndpoint(typeof(IConsoleInterface), new NetNamedPipeBinding(), "FrbConsolePipe");
_host.Open();
}
public void Dispose()
{
_host.Close();
}
}
クライアントで次のコードを使用して接続を確立します。
protected Callbacks _callbacks;
protected IConsoleInterface _proxy;
protected void ConnectToConsoleServer()
{
_callbacks = new Callbacks();
var factory = new DuplexChannelFactory<IConsoleInterface>(_callbacks,
new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/FrbConsolePipe"));
_proxy = factory.CreateChannel();
_proxy.ProcessInput("Connected");
}
だから何が起こるかというと、myConnectToConsoleServer()
が呼び出されてから_proxy.ProcessInput("Connected");
。私のゲーム(サーバー上)では、ProcessInput
呼び出しによって引き起こされた出力がすぐに表示されますが、クライアントはまだ_proxy.ProcessInput()
呼び出しで停止しています。
1分後、クライアントはJITを取得しますが、TimeoutException
同時にメッセージボックスメッセージが表示されます。
したがって、明らかに、コマンドがすぐに送信されるだけでなく、コールバックが正しく呼び出されます。では、なぜタイムアウト例外が発生するのですか?
注:MessageBox呼び出しを削除しても、この問題が発生するため、GUIがコールバック応答をブロックする問題ではありません。