2

通常、スレッドのリストがあります。各スレッドは、親コントロールと通信してデータグリッドビューにデータを入力するWebブラウザーコントロールを参照します。私がする必要があるのは、ユーザーが datagridviewButtonCell のボタンをクリックすると、対応するデータが、最初にメイン スレッドと通信した子スレッド内の webbrowser コントロールに送り返されることです。しかし、これを行おうとすると、次のエラーメッセージが表示されます

「基礎となる RCW から分離された COM オブジェクトは使用できません。」

私の問題は、関連する Web ブラウザー コントロールを参照する方法がわからないことです。誰でも私にできる助けをいただければ幸いです。

使用言語は c# winforms .Net 4.0 対象

コードサンプル:

ユーザーがメイン スレッドの [開始] ボタンをクリックすると、次のコードが実行されます。

プライベート ボイド StartSubmit(オブジェクト idx) {

/*

Webbrowser コントロールから継承された「myBrowser」を初期化するために新しいスレッドによって使用されるメソッド 各送信者オブジェクトは、オブジェクトの機能に関する詳細を保持する「myBrowser」と呼ばれるカスタム コントロールです。

*/

//index: スレッド ID を表す整数値です

int インデックス = (int)idx;

//submitters[index] は「myBrowser」コントロールのインスタンスです

submitters[index] = new myBrowser();

//スレッド整数 ID

submitters[index]._ThreadNum = index;

// 使用される命名規則 'browser' + スレッド インデックス

submitters[index].Name = "browser" + index;

// 'myBrowser' クラスにリストを設定して、メイン スレッドで見つかったリストのコピーを保持します

submitters[index]._dirs = dirLists[index];

// 「myBrowser」コントロールで発生する可能性のある JavaScript エラーを抑制します

submitters[index].ScriptErrorsSuppressed = true;

//eventHandler を実行

submitters[index].DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted);

// datagridview の次の未開封のアドレスに進み、そのアドレスをナビゲートします

//「myBrowser」コントロール内。

SetNextDir(submitters[index]);

}

private void btnStart_Click(オブジェクト送信者, EventArgs e) {

  // used to fill list<string> for use in each thread.

  fillDirs();

  //connections is the list<Thread> holding the thread that have been opened
  //1 to 10 maximum

  for (int n = 0; n < (connections.Length); n++)

  {

     //initialise new thread to the StartSubmit method passing parameters

     connections[n] = new Thread(new ParameterizedThreadStart(StartSubmit));

     // naming convention used conn + the threadIndex ie: 'conn1' to 'conn10' 

     connections[n].Name = "conn" + n.ToString();

     // due to the webbrowser control needing to be ran in the single
     //apartment state

     connections[n].SetApartmentState(ApartmentState.STA);

     //start thread passing the threadIndex

     connections[n].Start(n);

  }

}

「myBrowser」コントロールが完全にロードされたら、datagridview で見つかった行に入力するデータを介してロードされた Web ページで見つかった Web フォームにフォーム データを挿入します。ユーザーが行のさまざまな領域に関連する詳細を入力すると、DataGridViewButtonCell をクリックして、入力されたデータを収集し、子スレッドで見つかった対応する「myBrowser」オブジェクトに送り返す必要があります。

ありがとうございました

4

2 に答える 2

1

このエラーは、COM オブジェクトをラップしているマネージ オブジェクト (おそらく WebBrowser コントロールですが、詳細な情報がないとわかりません) が破棄されたことを示しています。つまり、マネージド オブジェクトはまだ存在しますが (ガベージ コレクションは行われていません)、IDisposable.Dispose() が呼び出されています (これにより、COM オブジェクトである WebBrowser コントロールが解放されます)。

ちなみに、RCW は Runtime Callable Wrapper の略です。

マネージ ラッパーを介して参照しようとしている COM オブジェクトに IDisposable.Dispose が呼び出されていないことを確認します (直接、またはusingブロックのスコープを離れるなどして)。

于 2012-11-12T19:48:16.627 に答える
0

COM オブジェクトは参照カウントされます ( IUnknownを参照してください)。obj->AddRef参照カウントをインクリメントし、obj->Release()デクリメントします。参照カウンターがゼロになると、オブジェクトはそのメモリの割り当てを解除して消えます。これが、このエラーが発生したときに発生したことです。

Dispose必ずしも呼び出す必要はありませんRelease- COM オブジェクトに対してそれを行う方法は、Marshal.ReleaseComObjectを呼び出すことです。ただし、オブジェクトをファイナライズすると解放されます。Web ブラウザー コントロールがスコープ内にあることを確認し、メイン UI スレッド以外のスレッドで実際にアクセスされないようにしてください。

于 2012-11-12T19:56:37.730 に答える