0

COM を使用するメソッドを起動する必要があるコンソール アプリケーションがあります。プログラムは [STAThread] で始まります。プログラムは、タイマー プロセスを使用していない場合は正しく実行されますが、タイマーを使用している場合はコンソールへのブロックが発生するようです。

System.Threading.Timer と System.Timers.Timer を使用しましたが、どちらも機能しませんでした。現在、COM を使用するメソッド (Transmit()) を呼び出すスレッドを追加しました。Console.Readline でメイン スレッドをクリアすると、プログラムは COM オブジェクトがブロックされた場所から再開しますが、もちろんプログラムは終了し、必要なタイマー機能が失われます。

コンソール アプリケーションを使用しているときに、SynchronizingObject を設定して ISynchronizeInvoke コールバックを取得する方法がわかりませんでした。

複数のスレッドを探しているわけではありません。Transmit メソッドを定期的に呼び出して、コンソールに結果を返しながら COM を操作する必要があるだけです。

class Program
{
    private static System.Timers.Timer transTimer;

    [STAThread]
    static void Main(string[] args)

       {
                transTimer = new System.Timers.Timer();
                transTimer.Enabled = true;
                transTimer.Interval = 6000;
                transTimer.Elapsed += new System.Timers.ElapsedEventHandler(transTimer_Elapsed);
                transTimer.Start();
                Console.ReadLine();
                transTimer.Dispose();
                return;
            }


    static void transTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (transTimer.Enabled)
        {
            transTimer.Enabled = false;
            Thread thread = new Thread(Transmit);
            thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
            thread.Start();
            thread.Join(); //Wait for the thread to end
            transTimer.Enabled = true;
        }
    }
4

2 に答える 2

2

重要なシングル スレッド アパートメント (STA) 要件に違反しています。メッセージ ループをポンピングする必要があります。これがないと、COM は、ワーカー スレッドから COM コンポーネントを作成したスレッドへの呼び出しをマーシャリングできません。これは、コンポーネントがスレッドセーフな方法で使用されるようにするために必要です。問題は、タイマーを使用したことではなく、スレッドを使用したことです。観察可能な効果は、呼び出しがデッドロックすることです。

コンソール アプリでメッセージ ループを取得するのは困難です。回避策の 1 つは、Main() メソッドで COM コンポーネントを作成するのではなく、マーシャリングが不要になるようにワーカー スレッドで COM コンポーネントを作成することです。ループ内で Sleep() を呼び出して、ピリオド呼び出しを実装します。

別の回避策は、[STAThread] 属性を使用しないことです。次に、COM は STA スレッドを自動的に作成して、COM コンポーネントに安全なホームを提供します。このスレッドは、メッセージ ループもポンピングします。すべての呼び出しがマーシャリングされるようになりました。多数の呼び出しを行う場合は避けてください。

于 2011-08-23T05:43:47.927 に答える
0

メッセージ ポンプを設定する .NET の方法は、Application.Run() です。別の専用スレッドから呼び出し、フォームを取り込まないオーバーロードを使用します。COM コードをそのスレッドに、コンソール コードをメイン スレッドに保持すると、コンソールが COM ロジックをブロックするという問題は発生しません。COM ロジックと対話するタイマーが必要な場合は、COM スレッドで開始された System.Windows.Forms.Timer オブジェクトを使用します。そうすれば、そこからのコールバック/イベントも COM スレッドで実行されます。

于 2011-08-23T15:38:15.923 に答える