質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

4782閲覧

IPC通信でクライアントからホストのイベントを実行すると「別のスレッドが所有しているのでオブジェクトにアクセス出来ません」と言われる

Fushihara

総合スコア52

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2017/10/29 04:15

質問に使用したVisualStudioのソリューションファイル一式は以下のgithubに公開しております。
cloneして、slnを開いてコンパイルしexeを二つ実行すると即再現出来るかと思います。
https://github.com/fushihara/cs-ipc-message-question

wpfアプリケーションでIPC通信を行いたいと思い、以下のCLIアプリでのサンプルをwpfで動くように改造しています。
https://code.msdn.microsoft.com/windowsdesktop/IPC-917071bc/view/Discussions#content

上記サイトのコードの中身は、アプリ起動時にMutexを取得。取得成功したらIPCサーバーとしてクライアントの接続を待機。
アプリ起動後にMutexの取得に失敗したらクライアントとして前述のIPCサーバーに接続し、クライアント側からサーバー側にメッセージを送信する。 という内容です。

MSDN上にあるcliのコードは問題なく動いています。

この処理をwpfアプリで使おうと思い、簡単なGUIを作って上記コードのロジックを移植してみました。

cs

1this.ipc = new IpcMessageSender<string>("sample", "sample"); 2if (ipc.IsCadet) { 3 var result = ipc.SendMessage(string.Format("{0:HH時mm分ss秒}です。後続プロセスが起動しました。", DateTime.Now)); 4} else { 5 // IPCでオブジェクトを受信したとき発生します。 6 ipc.MessageReceived += (a, b) => { 7 this.addLog($"受信[{b.Message}]"); 8 return "受信しました(ホストより)"; 9 }; 10}

IPCの処理としてはインスタンスを作る、ifでサーバーとクライアントを分岐する。サーバーの場合はメッセージ受信時のイベントをセットする。クライアントの時はサーバーにメッセージを送る。だけです。

このコードを実行すると、一回目の起動 つまりサーバー側としての起動は問題なく立ち上がりますが、一回目の起動をしたまま二回目の起動 つまりクライアント側としての起動時、SendMessageを呼ぶ時に下記のようなエラーが出てしまいます。

イメージ説明

wpfのテキストフォームであれば非UIスレッドからは操作できないと分かるのですが、イベントが別スレッドから操作出来ないというのは、どのように解決したらよいのでしょうか。
質問内容が具体的でなく申し訳ありませんが、よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

イベントが別スレッドから操作出来ないというのは、どのように解決したらよいのでしょうか。

UIスレッドのコンテキストで実行できるよう、Dispatcher.Invokeを使用すれば良いと思います。

C#

1 public partial class MainWindow : Window { 2 private IpcMessageSender<String> ipc; 3 public MainWindow() { 4 InitializeComponent(); 5 this.addLog("コンストラクタ"); 6 } 7 8 private void addLog(String message) { 9 String time = DateTime.Now.ToString("HH:mm:ss.fff"); 10       // ここでException 11 // this.logText.Text += $"{time} {message}\n"; 12 13 // MainWindowのスレッドコンテキストで実行 14 this.Dispatcher.Invoke( 15 new Action(() => { 16 this.logText.Text += $"{time} {message}\n"; 17 })); 18

実際にcloneしてビルドして確認しました。上記のコードは動作させてすぐ、同じExceptionが発生した部分です。同じ原因かと思いましたので、全部のコードは確認していません。同じようにUIのコントロールに触る部分ではこのようにすれば良いと思います。SendMessageも同様に対応すればよろしいかと。

尚、当方の環境の都合で.NET Framework 4.7ではなく、4.6.1 で確認しています。

投稿2017/10/29 05:05

dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Fushihara

2017/10/29 05:24

ありがとうございます。SendMessageを呼ぶ段階でエラーが出ているのでaddLogまで処理が行っているとは思いもしませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問