GUIも追加したいWindowsサービスを使用しています。サービスで ServiceHost オブジェクトを作成し、WCF 名前付きパイプ サービスをホストし、コンソール アプリケーションで WCF サービスを使用し、サービスからコールバック応答 (サーバーから接続されたクライアントに送信されるメッセージ) を取得することで、概念実証を行いました。これは、私のコンソールアプリケーションが実行され、中断や遅延なしでサービスからの応答を取得するのに最適です。
ただし、ボタンをクリックしてWCFサービスを呼び出すときにWPF GUIアプリケーションで同じことを行うと、UIスレッド全体がフリーズし、数分後に例外がスローされ、メッセージコールバックでUIが更新されます(サーバーが送信します接続されたクライアントへのメッセージ) が、例外がスローされたため、サービスからの戻り値はすべて失われます。
私が受け取った2つの例外メッセージは論文です(最も一般的なのは最初のものです):
1: net.pipe に送信された要求アクション :/ / localhost / PipeGUI は、指定されたタイムアウト (00:00:59.9989999) 内に応答を受信しませんでした。この操作に割り当てられた時間は、より長いタイムアウトの一部であった可能性があります。これは、サービスがまだ操作を処理中であるか、サービスが応答メッセージを送信できなかったことが原因である可能性があります。アクションの期限を上げ (チャネル/プロキシをアイコン テキスト チャネルに入力し、プロパティの [操作のタイムアウト] を設定して)、サービスがクライアントに接続できることを確認します。
2:通信オブジェクト System.ServiceModel.Channels.ServiceChannel は、キャンセルされたため、通信に使用できません。
なぜこれが起こっているのか誰にも分かりますか?必要に応じて、さらにコードを投稿できます。
UPDATE 、参照用にコードを追加
public interface IClientCallback
{
[OperationContract(IsOneWay = true)]
void MessageRecived(string message);
}
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IClientCallback))]
public interface IPipeServiceContract
{
[OperationContract]
string Hello();
[OperationContract]
void Message(string msg);
[OperationContract(IsInitiating = true)]
void Connect();
[OperationContract(IsTerminating = true)]
void Disconnect();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true, UseSynchronizationContext = false)]
public class PipeService : IPipeServiceContract
{
List<IClientCallback> _clients = new List<IClientCallback>();
public string Hello()
{
PublishMessage("Hello World.");
return "Return from method!";
}
public void Connect()
{
_clients.Add(OperationContext.Current.GetCallbackChannel<IClientCallback>());
}
public void Disconnect()
{
IClientCallback callback = OperationContext.Current.GetCallbackChannel<IClientCallback>();
_clients.Remove(callback);
}
void PublishMessage(string message)
{
for (int i = _clients.Count - 1; i > 0; i--)
{
try
{
_clients[i].MessageRecived(message);
}
catch (CommunicationObjectAbortedException coae)
{
_clients.RemoveAt(i);
}
catch(CommunicationObjectFaultedException cofe)
{
_clients.RemoveAt(i);
}
}
}
public void Message(string msg)
{
PublishMessage(msg);
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged, IClientCallback
{
public ServiceController Service { get; set; }
protected IPipeServiceContract Proxy { get; set; }
protected DuplexChannelFactory<IPipeServiceContract> PipeFactory { get; set; }
public ObservableCollection<ServerActivityNotification> Activity { get; set; }
public override void BeginInit()
{
base.BeginInit();
PipeFactory = new DuplexChannelFactory<IPipeServiceContract>(this, new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/PipeGUI"));
}
public MainWindow()
{
InitializeComponent();
Activity = new ObservableCollection<ServerActivityNotification>();
Service = ServiceController.GetServices().First(x => x.ServiceName == "Server Service");
NotifyPropertyChanged("Service");
var timer = new DispatcherTimer();
timer.Tick += new EventHandler(OnUpdate);
timer.Interval = new TimeSpan(0, 0, 0, 0, 850);
timer.Start();
if (Service.Status == ServiceControllerStatus.Running)
{
Proxy = PipeFactory.CreateChannel();
Proxy.Connect();
}
}
void OnUpdate(object sender, EventArgs e)
{
Service.Refresh();
NotifyPropertyChanged("Service");
StartButton.IsEnabled = Service.Status != ServiceControllerStatus.Running ? true : false;
StopButton.IsEnabled = Service.Status != ServiceControllerStatus.Stopped ? true : false;
if (PipeFactory != null && Service.Status == ServiceControllerStatus.Running)
{
Proxy = PipeFactory.CreateChannel();
Proxy.Connect();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
private void OnStart(object sender, RoutedEventArgs e)
{
try
{
Service.Start();
}
catch
{
Service.Refresh();
}
}
private void OnStop(object sender, RoutedEventArgs e)
{
try
{
if (Proxy != null)
{
Proxy.Disconnect();
PipeFactory.Close();
}
Service.Stop();
}
catch
{
Service.Refresh();
}
}
public void MessageRecived(string message)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
ServerActivityNotification log = new ServerActivityNotification { Activity = message, Occured = DateTime.Now };
Activity.Add(log);
ListBoxLog.ScrollIntoView(log);
NotifyPropertyChanged("Activity");
}));
}
private void OnHello(object sender, RoutedEventArgs e)
{
try
{
Proxy.Message(txtSendMessage.Text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
}