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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework

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

Q&A

解決済

1回答

1877閲覧

【C#】【.net】常駐アプリ用のコンポーネントでツールに付与したイベントが動かない

hasshy

総合スコア102

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework

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

0グッド

0クリップ

投稿2020/06/12 07:57

編集2020/06/12 08:01

Visual StudioでC#のアプリケーションを開発しています。
常駐アプリを作りたいのでタスクバーにアイコンを出力して、アイコンにアプリケーション終了用の右クリックメニューを持たせています。

アプリでは、接続されたデバイスを監視する必要があります。
この処理を実装すると、右クリックメニューが機能しない問題が発生しました。

監視、右クリックメニューのどちらかずつであれば機能させられますが、両方同時に機能をさせられません。
恐れ入りますが、何か解決方法があればご教示頂けないでしょうか?

状況

カードを読み込む処理自体は作成出来ました。
機能を常駐アプリに統合する所で躓いています。

実現したい事

外付けのカードリーダーでカードを読み取って、
別のアプリケーションに対して何らかの処理をするというアプリケーションを作りたいです。

常にカードを読み込める状態にしたいので、常駐アプリとして実装しようと考えています。

デザイン

NotifyIconWrapperと言うコンポーネントを作成しました。
タスクバーにアイコンを表示し、右クリックメニューが表示できるように下記のツールを配置しています。

  • NotifyIcon
  • ContextMenuStrip

イメージ説明

ContextMenuStripには、アプリ終了用にtoolStripMenuItemExitと言うアイテムを追加しています。

ソース

NotifyIconWrapper.cs

「終了」メニューだけなので次のようなソースです。
常に動かしたい処理はthis.nfcMain.start()の部分です。
詳細は後述しますが、カードリーダーの読み込み状態を維持するための関数です。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using CardReader.Classes.NfcReader; namespace Sample.Components { public partial class NotifyIconWrapper : Component { /// <summary> /// nfc接続用のクラス /// </summary> private NfcMain nfcMain; /// <summary> /// コンストラクタ /// </summary> public NotifyIconWrapper() { InitializeComponent(); // 終了メニューのイベントリスナーを設定 this.toolStripMenuItemExit.Click += new EventHandler(this.toolStripMenuItemExit_Click); // カードリーダースタンバイ開始 this.nfcMain = new NfcMain(); this.nfcMain.start(); } /// <summary> /// コンテナで初期化する場合のコンストラクタ /// </summary> /// <param name="container"></param> public NotifyIconWrapper(IContainer container) { container.Add(this); InitializeComponent(); } /// <summary> /// コンテキストメニュー、「終了」のイベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void toolStripMenuItemExit_Click(object sender, EventArgs e) { System.Windows.Application.Current.Shutdown(); } } }

NfcMain.cs

カードリーダー用のクラスです。
原因になっている個所を抜粋して記載します。
やっている事はカードリーダーを起動して、常にカードリーダーから状態を監視するという処理です。

参考までに下記のサイトを参考にしています。
PC/SC APIを用いてSuicaカードの利用履歴情報の読み取り

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace Sample.Classes.NfcReader { /// <summary> /// カードリーダーの制御統括クラス /// </summary> class NfcMain { /// <summary> /// カードリーダー読み込み /// </summary> public void start() { IntPtr context = establishContext(); List<string> readerList = getReaders(context); NfcApi.SCARD_READERSTATE[] readerStateArray = initializeReaderState(context, readerList); bool quit = false; while (!quit) { waitReaderStatusChange(context, readerStateArray, 1000); // リーダーの状態が、カード接続状態になったら読み込み処理を実行 if ((readerStateArray[0].dwEventState & NfcConstant.SCARD_STATE_PRESENT) == NfcConstant.SCARD_STATE_PRESENT) { ReadResult result2 = readCard(context, readerStateArray[0].szReader); SendCommand(context, readerStateArray[0].szReader); quit = true; } } // カードリーダーの接続状態を解除する uint ret = NfcApi.SCardReleaseContext(context); }

実行結果

タスクメニューにアイコンは表示されて、カードを読み込む処理は出来ます。
しかし、右クリックメニューが表示されません。

原因と思われる個所と所見

NfcMainのstart関数で、while分を用いたループをしているのが起因している可能性があります。
ループ処理をコメントアウトするとメニューが表示できます。

監視するためには繰り返しで状況を見ないといけないと思うのですが、そもそもコンストラクタで繰り返しの処理は使えないのでしょうか?

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

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

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

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

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

YAmaGNZ

2020/06/12 08:01

Taskなどを利用して別スレッドで実行してみてはどうでしょうか?
hasshy

2020/06/12 08:04 編集

ご教示ありがとうございます。 リーダー(裏で処理をする?)とメニューでスレッド分けるのですね。 Taskについては知らなかったので調べてみます。
guest

回答1

0

ベストアンサー

NfcMainを別スレッドで動作させるようにしましょう。

メインスレッド(UIスレッド)でループさせてしまうと、UI動作に処理がまわってこなくなります

投稿2020/06/12 08:24

y_waiwai

総合スコア88024

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

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

hasshy

2020/06/12 08:29

何時もありがとうございます。 解釈が間違っていれば申し訳ありませんが、コンストラクタで以降の処理が止まっていたのですね。 スレッドの情報を集めてみます。 ご指摘ありがとうございます。
y_waiwai

2020/06/12 08:38

コンストラクタでNfcMainをstartさせているんで、ここでのカード待ちでUI動作が止まってしまいますね
hasshy

2020/06/13 08:07

度々ご解説していただきありがとうございます。 タスク化したらUIも動くようになりました。 コンストラクタでタスクを発行するのが一般的なのか知見が無く判断しかねておりますが…
y_waiwai

2020/06/13 08:13

この場合はコンストラクタでタスク生成しても構わないでしょう。 コンストラクタの途中では、そのクラスがまだ生成されてないってことなんで、タスク中にそのクラスをどーこ~する処理があるとまずいですが。
hasshy

2020/06/14 17:17

ありがとうございます! アドバイスを頂けて安心いたしました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問