- PR -

MessageQueueが受信してくれません

1
投稿者投稿内容
いも
常連さん
会議室デビュー日: 2006/01/26
投稿数: 31
投稿日時: 2006-11-09 11:23
いつもお世話になっております。
VisualStudio2005でWindowsApplicationを開発しています。

MessageQueueを使ってタスク間のやりとりをしたいのですが、たまに受信が出来ません。
何か受信出来ない条件があるのでしょうか??

今のところ
1)PC起動後30秒間ほどはキューの作成が出来ないらしい
2)キューがあったらパスを設定、無かったら作成してBeginReceive()をする。
 前者の場合問題無く受信するが、後者の場合アプリケーションを再立ち上げしないと受信しない。
という感じです。

(1)はあまり困らないのですが、(2)に困っています。
BeginReceive()の後メッセージを送信しても、ReceiveCompletedイベントが発生しません。
間違いなくキューを作成する部分がおかしいのだろうとは思うのですが…。

以下該当コードです。
どなたかおかしなところを見つけていただけませんでしょうか…。


//既にあればパスを設定するだけ
if (MessageQueue.Exists("マシン名\\private$\\キュー名") == true)
{
MQ.Path = "FormatNAME:DIRECT=OS:マシン名\\private$\\キュー名";
}
//無かったら作成
else
{
MQ = MessageQueue.Create("マシン名\\private$\\キュー");
MQ.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Allow);
MQ.SetPermissions("ANONYMOUS LOGON", MessageQueueAccessRights.FullControl, AccessControlEntryType.Allow);
}

MQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(TYPE_MQ) });

//受信開始
MQ.BeginReceive();
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2006-11-09 12:24
送信したメッセージがキューに書き込まれていることは確認していますか?
また、アプリケーション内でキューを作成しなければならない理由はなんでしょうか。
キュー名が固定されているのであれば、あらかじめ作成しておいたほうがいいと思う
のですが。
いも
常連さん
会議室デビュー日: 2006/01/26
投稿数: 31
投稿日時: 2006-11-09 13:49
コメントありがとうございます。

送信したメッセージが書き込まれているのは確認しています。
ただ、今気づいたのですが次の場合は書き込まれませんでした

便宜上『受信』と『送信』のプログラムがあるとします。
(1)『受信』が立ち上がると同時にキューを確認し、無いので作る
(2)『受信』はBeginReceive()
(3)『送信』を立ち上げ、キューのパスを設定し送信する←書き込まれない
(4)もういちど送信する←書き込まれるが受信されない

1度目だけ送信されず、次からは送信されていました。
これはリトライで解決出来るのであんまり問題ではないです。

次の場合は受信されます。
(1)『受信』が立ち上がると同時にキューを確認。あるので作らない。
(2)『受信』はBeginReceive()
(3)『送信』を立ち上げ、送信ボタンを押すとキューのパスを設定し送信する←書き込まれ受信される

(1)『送信』で送信ボタンを押すと同時にキューを確認。無いので作って送信する
(2)『受信』が立ち上がると同時にキューを確認。あるので作らない。
(3)『受信』はBeginReceive()←受信する

キュー作成後Receive出来るようになるまでの時間 >> キュー作成後Send出来るようになるまでの時間
なんでしょうか??
試しにBeginReceive()をする前に3秒ほどスリープを入れてみましたが駄目でした。


キューはあらかじめ作っておく予定です。
ただ何かがあってキューが消えてしまったり壊れてしまった場合(そんなことがあるのかわかりませんが)
起動時に確認して作成させたいと思っています。
いも
常連さん
会議室デビュー日: 2006/01/26
投稿数: 31
投稿日時: 2006-11-09 14:06
自己解決です…お騒がせしました。

MQ = MessageQueue.Create("マシン名\\private$\\キュー");
が、良くなかったみたいです。
http://msdn2.microsoft.com/ja-jp/library/5yka0xsf(VS.80).aspx
を見てそのように書き、コンパイルも通り、例外も出ていなかったのですが…


次のようにしました


//無かったら作る
if (MessageQueue.Exists("マシン名\\private$\\キュー") != true)
{
MessageQueue.Create("マシン名\\private$\\キュー");
}

MQ.Path = "FormatNAME:DIRECT=OS:"マシン名\\private$\\キュー";
MQ.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Allow);
MQ.SetPermissions("ANONYMOUS LOGON", MessageQueueAccessRights.FullControl, AccessControlEntryType.Allow);
MQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(TS.TYPE_MSGQ_COMM) });

// 受信開始
MQ.BeginReceive();
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2006-11-09 14:18
引用:

いもさんの書き込み (2006-11-09 14:06) より:
MQ = MessageQueue.Create("マシン名\private$\キュー");
が、良くなかったみたいです。


というのはどこで判断したのですか?
APIリファレンスを見る限り問題なさそうですが。

それから直接関係はありませんが、

引用:

キューはあらかじめ作っておく予定です。
ただ何かがあってキューが消えてしまったり壊れてしまった場合(そんなことがあるのかわかりませんが)
起動時に確認して作成させたいと思っています。


この仕様はほんとうにこれでいいのでしょうか。MQの用途がわからないのではっきりと
したことはいえませんが、システムになんらか障害がある場合はきちんと障害がある
ことを認識できるようにしたほうがいいと思います。
いも
常連さん
会議室デビュー日: 2006/01/26
投稿数: 31
投稿日時: 2006-11-09 14:44
引用:

というのはどこで判断したのですか?
APIリファレンスを見る限り問題なさそうですが。



私にもわかりません…とにかくここで返ってきたMessageQueue型の何かを代入せずに
作るだけ作ってあとでパスを設定したらうまくいきました…。

引用:

この仕様はほんとうにこれでいいのでしょうか。MQの用途がわからないのではっきりと
したことはいえませんが、システムになんらか障害がある場合はきちんと障害がある
ことを認識できるようにしたほうがいいと思います。



以前設定ファイルのファイル名を書き換えられ動かなくなったということがあったそうなので、
まさかメッセージキューの名前を変えたり消してしまったりすることは無いでしょうけれども
念のため毎回確認して無ければ作るようにしています。
キューは『受信』『送信』ともに起動中にしか使わないです。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2006-11-09 16:17
引用:

いもさんの書き込み (2006-11-09 14:44) より:
私にもわかりません…とにかくここで返ってきたMessageQueue型の何かを代入せずに
作るだけ作ってあとでパスを設定したらうまくいきました…。


だとすると、問題が解決したというのは確実ではないですね。

引用:

以前設定ファイルのファイル名を書き換えられ動かなくなったということがあったそうなので、
まさかメッセージキューの名前を変えたり消してしまったりすることは無いでしょうけれども
念のため毎回確認して無ければ作るようにしています。
キューは『受信』『送信』ともに起動中にしか使わないです。


送信側はキューがなければどうするのでしょうか。また、受信プログラムは一つの
キューに対して一つだけでしょうか。もし複数のプログラムがキューの存在を確認して
作成する、ということになると、race conditionに陥る可能性もありますね。まあ
現実問題としてキューが存在しない、ということ自体が稀なことでしょうから杞憂では
あるんでしょうが。
いも
常連さん
会議室デビュー日: 2006/01/26
投稿数: 31
投稿日時: 2006-11-10 09:03
引用:

だとすると、問題が解決したというのは確実ではないですね。



はい…残念ながら。
ただここをMQ = MessageQueue.Create(パス)とするとまた同じ現象(再起動しないと受信しない)になるので
ここが問題なんだと思います。ヘルプでCreate()やReceiveCompletedなどを見ていますが未だ良くわかりません

引用:

送信側はキューがなければどうするのでしょうか。また、受信プログラムは一つの
キューに対して一つだけでしょうか。もし複数のプログラムがキューの存在を確認して
作成する、ということになると、race conditionに陥る可能性もありますね。まあ
現実問題としてキューが存在しない、ということ自体が稀なことでしょうから杞憂では
あるんでしょうが。



『送信』『受信』ともに起動時に自分のキューを1つ作る感じです。
送信、受信というのは今思うと語弊を招く表現でした。
プログラムが2つあって、それぞれが自分のキューを1つずつ持ちます。
メッセージは相手のキューに対して送り、自分のところにきたメッセージを受信する感じです。
万が一キューが無かった場合、自分のキューだけを作るので、作成命令が過剰になってしまうことはないです。
片方だけ無かったという場合でも両方無かった場合でも(実際はプログラムは2つでなくたくさんあるのですが)
再起動すれば大丈夫になる予定です。
1

スキルアップ/キャリアアップ(JOB@IT)