2012-01-07 13 views
3

私は通常のUIスレッドとバックグラウンドワーカーを持つ単純なアプリを持っています。バックグラウンドワーカーでは、LinkLabelを動的に作成してFlowLayoutPanelに配置する必要があります。これを行うには、LinkLabelの親をFlowLayoutPanelに設定する必要があります。マルチスレッド、アクセスUIコントロール

ここに私が現在持っているコードがありますが、「l.Parent = panel;」という行の悪意のある「クロススレッド操作が無効です」というメッセージが表示されます。

私は、マルチスレッドの操作にかなり新しいですが、私は正しく起動したと思いましたが、明らかにそうではありませんでした。助言がありますか?

LinkLabel l = new LinkLabel(); 
if (rssFeedPanel.InvokeRequired) { 
    FlowLayoutPanel panel = null; 
    rssFeedPanel.Invoke(new MethodInvoker(delegate { panel = rssFeedPanel; })); 
    l.Parent = panel; 
} 
else 
    l.Parent = rssFeedPanel; 

答えて

3

もう1つのスレッドで実際にParentプロパティを設定する必要があります。

LinkLabel l = new LinkLabel(); 
if (rssFeedPanel.InvokeRequired) { 
    rssFeedPanel.Invoke(new MethodInvoker(delegate { 
     l.Parent = rssFeedPanel; 
    })); 
} 
else 
    l.Parent = rssFeedPanel; 

一般に、UIコントロールのメンバーにアクセスすることを含むほぼすべての操作は、UIスレッドからのみ実行できます。いくつかの明白な例外は、Invoke,InvokeRequired,BeginInvoke、およびBackgroundWorkerクラスのメソッドの一部です。

この場合は、Invokeの代わりにBeginInvokeを使用することもできます。

+0

ありがとう! – Hammy

+0

興味深いことに、if(Dispatcher.Thread == Thread.CurrentThread)を使用することはできませんし、Dispatcher.BeginInvoke(new EventHandler ())を呼び出すと、それぞれのInvokeRequiredコントロール?ちょうど脳のおならですが、できれば、少し速いと確信しています。 (イベントや何かを起動し、 'EventArgs'を通して物を渡す必要がありますが、それはとても簡単です) – aevitas

+0

' Dispatcher.Thread'は静的ではないので、UIスレッドのインスタンスが必要です。速くなることについては、私はそれを疑う。コードを見ることで、コントロールウィンドウが作成されていればほぼ同じことになると思います。ウィンドウが作成されていない場合は、 'Control.InvokeRequired'が速いと思います。 –

3

ロジックを1つのメソッドに入れ、まずInvokeRequiredがそのメソッドをInvoke内で呼び出すかどうかを確認し、そうでない場合は直接呼び出すことをお勧めします。

if (rssFeedPanel.InvokeRequired) { 
    rssFeedPanel.Invoke(new MethodInvoker(delegate 
    { 
     AddLabel(); 
    })); 
} 
else AddLabel(); 

そしてAddLabel方法であなたのロジックを置く:助けを

private void AddLabel() 
{ 
    LinkLabel l = new LinkLabel(); 
    l.Parent = rssFeedPanel; 
} 
関連する問題