4

Windowsフォームアプリケーションで、リモートマシンの共有フォルダーにアクセスするユーザーの機能をテストしようとしています。私がこれを行っている方法(そしてもっと良い方法があると確信しています...しかし私はそれらを知りません)は、リモートマシン上の特定のディレクトリの存在をチェックすることです(私はこれを行っています組織内で直面しているファイアウォール/その他のセキュリティ制限のため)。ユーザーが共有フォルダーにアクセスする権限を持っている場合、すぐに戻りますが、そうでない場合は、永久にハングします。これを解決するために、チェックを別のスレッドにスローし、1000ミリ秒だけ待ってから、ユーザーが共有にアクセスできないと判断しました。ただし、これを行うと、同じスレッドで実行されなかったかのようにハングします。

何がハングしているのですか?どうすれば修正できますか?それが別のスレッドにあるという事実は、私がバックグラウンドでそれ自身でスレッドを終了させることを可能にするだろうと思います。

これが私のコードです:

bool canHitPath = false;
Thread thread = new Thread(new ThreadStart(() =>
{
    canHitPath = Directory.Exists(compInfo.Path);
}));
thread.Start();
thread.Join(1000);

if (canHitPath == false)
{
    throw new Exception("Cannot hit folder: " + compInfo.Path);
}

編集:例外をスローする行はHITであることを追加する必要があると思います。私はこれをデバッグして検証しました...しかし、例外がスローされたとき、それは私のプログラムがハングしたときです。(例外が呼び出し元のメソッドでキャッチされ、デバッガーでcatchステートメントに到達しないことも追加する場合があります。)

4

5 に答える 5

3

あなたのコメントは、例外が実際にスローされてキャッチされることを明確にしています。したがって、コードの実行は少なくともこのコードを超えて進行し、スニペットからは何をしているのかわかりません。

間違いを1つ犯しました。スレッドのIsBackgroundプロパティをtrueに設定するのを忘れました。これがないと、プログラムを終了できません。これは、「ブロックしている」と結論付ける1つの方法です。この推測が正確でない場合は、メインスレッドの呼び出しスタックを確認して、メインスレッドが何をしているのかを把握する必要があります。管理されていないデバッグサポートをオンにし、Microsoft Symbol Serverを有効にして、管理されている部分だけでなく、呼び出しスタック全体を表示できるようにすることで、最適にキャプチャできます。

まったく異なるアプローチは、Pingクラスを使用してサーバーをプローブすることです。

于 2012-04-05T17:55:10.483 に答える
2

私の推測では、これは次の理由で発生すると思います。

canHitInstallPath = Directory.Exists(compInfo.InstallPath);

このExistsメソッドは、トレッドの実行フローを保持します(これは中断のない呼び出しです)。30秒間ハングした場合、スレッドThread.Join(1000)は経過したかどうかを確認する機会が得られるまで30秒間待機します。

Thread.Join()メソッドは、スレッドオブジェクトが完了するまで、呼び出し元のスレッド(通常はアプリケーションの実行のメインスレッド)のみをブロックすることに注意してください。特定のスレッドの実行が終了するのを待っている間も、他のスレッドをバックグラウンドで実行することができます。

から:

Thread.Joinメソッド(System.Threading)

考慮すべきもう1つのこと:フォルダーが存在するかどうかを確認するだけでは、ユーザーがそのフォルダーに対してファイルを読み書きできるかどうかはわかりません。最善のオプションは、フォルダのファイルの書き込みまたは読み取りを試みることです。このようにして、ユーザーがそのフォルダー内のアクセス許可を持っていることを確認できます。

編集

あなたの場合、スレッドは、スレッドが終了するのを待っている間に他のことができる場合にのみ意味があります。あなたができない場合、それらのスレッドはまったくあなたを助けていません。

EDIT2

私の答えをサポートするためのリンク:ファイル記述子とマルチスレッドプログラム

EDIT3

最善のオプションは、キラースレッドを作成することです。このスレッドはDirectoryExists、X秒以上ハングするとスレッドを強制終了します。

于 2012-04-05T17:02:43.063 に答える
2

私は本当の問題を見つけました:

プロパティcompInfo.Pathは、リモートファイルシステムにディレクトリが存在するかどうかをチェックして、リモートマシンが64ビットかどうかを判断します。結果に応じて、異なる値を返します。チェックをコメントアウトしてみたところ、正常に実行されました。これは、例外のスローを回避できなかった理由を説明しています。例外のメッセージでcompInfo.Pathを呼び出します。

しかし、私たちは「本当の問題」から多くを学んだと思います。

  1. 質問に投稿したコードは(そのままで)完全に正常に機能します。
  2. thread.Join(int)は、スレッドがまだコードを実行している可能性があるという事実に関係なく、指定された時間間隔の後に終了します。
  3. 参加しているスレッドはIO操作を実行している可能性があり(したがって、ファイル/ディレクトリを拘束している)、thread.Join(int)を実行しても目的の結果が得られます。
  4. デバッガーの「ステップイン」ボタンを使用すると、多くのことが明らかになります...独自の「堅実な」コードについてもです。:)

あなたの助け、忍耐、そして思慮深いインプット/洞察にみんなに感謝します。

于 2012-04-06T15:04:56.740 に答える
0

たぶん、タスク並列ライブラリを見てください。TPLは、パフォーマンスを最大化するように設計されており、問題が何であれ処理できる可能性があります。それはまた、状況にとって完全にやり過ぎかもしれませんが。

于 2012-04-05T17:02:07.790 に答える
0

Thread.Joinは、呼び出されたスレッドが終了するまで、呼び出さたスレッドを保持するブロッキング呼び出しです。

基本的に、バックグラウンド作業を行うために新しいスレッドをスピンアップし、メインスレッドに終了するまで待機するように指示します。事実上、すべてを同期的に実行します。

于 2012-04-05T17:03:01.443 に答える