22

ラベルを更新するたびに、次 のエラーが発生しました。別のスレッドが所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。呼び出そうとしましたが、失敗しました。私はWPFフォームを使用しています。

delegate void lostfocs(string st);
   private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {

        Thread t = new Thread(modi);
        t.Start();
    }
 void modi()
    {
        try
        {
            label1.Content = "df";
        }
        catch
        {
            lostfocs ld = new lostfocs(up);
          //  ld.Invoke("df");
            object obj=new object();
            ld.Invoke("sdaf");
        }
    }
void up(string st)
    {
        label1.Content = st;
    }
4

6 に答える 6

42

Dispatcher.Invokeメソッドを使用します。

Dispatcher が関連付けられているスレッドで、指定されたデリゲートを同期的に実行します。

また

WPF では、DispatcherObject を作成したスレッドのみがそのオブジェクトにアクセスできます。たとえば、メインの UI スレッドからスピンオフされたバックグラウンド スレッドは、UI スレッドで作成された Button の内容を更新できません。バックグラウンド スレッドが Button の Content プロパティにアクセスするには、バックグラウンド スレッドが UI スレッドに関連付けられた Dispatcher に作業を委任する必要があります。これは、Invoke または BeginInvoke を使用して実行されます。Invoke は同期で、BeginInvoke は非同期です。操作は、指定された DispatcherPriority で Dispatcher のイベント キューに追加されます。

ラベルが UI スレッドで作成され、別のスレッドを介してその内容を変更しようとしているため、エラーが発生しています。ここで、Dispatcher.Invoke が必要になります。

この記事をチェックしてください WPF スレッドはディスパッチャーでよりレスポンシブなアプリを構築します

于 2012-05-29T08:59:43.833 に答える
17

これには Dispatcher を使用できます。あなたのコードは...

private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
    {
        try
        {
            label1.Content = "df";
        }
        catch
        {
            lostfocs ld = new lostfocs(up);
          //  ld.Invoke("df");
            object obj=new object();
            ld.Invoke("sdaf");
        }
    }
));
于 2012-05-29T09:02:24.627 に答える
11

Dispatcher.Invokeを使用する

    void modi()
    {
        if(!Dispatcher.CheckAccess())
        {
            Dispatcher.Invoke(
                    ()=>label1.Content = "df",DispatcherPriority.Normal);
        }
        else
        {
            label1.Content = "df";
        }
    }
于 2012-05-29T09:06:05.140 に答える
1

非 UI スレッドを 1 つ開始し、このスレッド内で 1 つの UI スレッドも開始しました。したがって、私の要件は、非 UI スレッド内で UI スレッドを実行するようなものです。このシナリオを処理すると、次の例外が発生しました。 「例外: 別のスレッドが所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。」

この場合、以下のように UI 要素の Dispatcher.Invoke メソッドを使用したところ、うまく機能しました。

if (m_contextWindow == null)
{   
    System.Threading.Thread newWindowThread = new System.Threading.Thread(new ThreadStart( () =>
    {
        // Create and show the Window
        m_contextWindow = new ContextWindow();
        m_contextWindow.DataContext = this;                            
        m_contextWindow.Show();
        // Start the Dispatcher Processing
        System.Windows.Threading.Dispatcher.Run();
    }));

    // Set the apartment state
    newWindowThread.SetApartmentState(ApartmentState.STA);
    // Make the thread a background thread
    newWindowThread.IsBackground = true;
    // Start the thread
    newWindowThread.Start();
}
else
{                     
    this.m_contextWindow.Dispatcher.Invoke(new ThreadStart(() => 
    {
        m_contextWindow.DataContext = this;
        if (m_contextWindow.Visibility == System.Windows.Visibility.Collapsed
         || m_contextWindow.Visibility == System.Windows.Visibility.Hidden)
            m_contextWindow.Visibility = System.Windows.Visibility.Visible;
    }));                            
}
于 2014-02-19T12:51:44.577 に答える
0
private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
            {
                try
                {
                    label1.Content = "df";
                }
                catch
                {
                    lostfocs ld = new lostfocs(up);
                    object obj = new object();
                    ld.Invoke("sdaf");
                }
            }));
        }
于 2012-05-29T09:51:26.060 に答える