首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无效的跨线程访问。错误

无效的跨线程访问。错误
EN

Stack Overflow用户
提问于 2011-11-23 10:18:04
回答 2查看 9K关注 0票数 0

我在silverlight有一个网页表格。

单击某个按钮的操作时,我想更新另一个控件,如图表、文本框等。

同时,当它填充图表或文本框时,我需要显示一个繁忙的指示器。

  1. 繁忙指示器应首先显示在屏幕上,
  2. 后面的图表值应得到更新,
  3. 图值将反映在屏幕上
  4. 繁忙指示器应隐藏

但问题是,当我尝试使用线程时,我得到了一个错误“无效的跨线程访问”。当线程正在访问UI控件时。我尝试过的四个步骤如下。

任何有价值的建议如何解决这个问题。

步骤1 =>尝试了线程

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.ComponentModel;
using System.Windows.Threading;


namespace SilverlightApplication2
{
  public partial class MainPage : UserControl
    {

        public MainPage()
        {
            InitializeComponent();



        }

        private void test1()
        {


            for (int i = 1; i < 10000; i++)
            {
                System.Diagnostics.Debug.WriteLine(i.ToString());
            }
        textbox1.Text="test";   //=> Throwing Error "Invalid cross-thread access."
            busyIndicator1.IsBusy = false;   //=> Throwing Error "Invalid cross-thread access."
        }



     private void button1_Click(object sender, RoutedEventArgs e)
         {
             busyIndicator1.IsBusy = true;

             Thread th1 = new Thread(test1);
             th1.Start();

         }

    }
}

步骤2 =>尝试了BackgroundWorker

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.ComponentModel;
using System.Windows.Threading;


namespace SilverlightApplication2
{
  public partial class MainPage : UserControl
    {

        public MainPage()
        {
            InitializeComponent();



        }

        private void test1()
        {


            for (int i = 1; i < 10000; i++)
            {
                System.Diagnostics.Debug.WriteLine(i.ToString());
            }
        textbox1.Text="test";   //=> Throwing Error "Invalid cross-thread access."
            busyIndicator1.IsBusy = false;   //=> Throwing Error "Invalid cross-thread access."
        }



     private void button1_Click(object sender, RoutedEventArgs e)
         {
             busyIndicator1.IsBusy = true;

            var bw = new BackgroundWorker();
            bw.DoWork += (s, args) =>
            {
                test1();  //Stuff that takes some time
            };
            bw.RunWorkerCompleted += (s, args) =>
            {
                busyIndicator1.IsBusy = false;
            };
            bw.RunWorkerAsync();              
         }

    }
}

步骤3 =>试图从后面的代码引发一个事件

代码语言:javascript
复制
public delegate void LinkToEventHandler();
public static event LinkToEventHandler Evt;

 private void button1_Click(object sender, RoutedEventArgs e)
 {
     busyIndicator1.IsBusy = true;

     Evt += new LinkToEventHandler(this.test1);
     Evt();
 }



private void test1()
{


    for (int i = 1; i < 10000; i++)
    {
        System.Diagnostics.Debug.WriteLine(i.ToString());
    }
    textbox1.Text="test";   //=> Throwing Error "Invalid cross-thread access."
    busyIndicator1.IsBusy = false;   //=> Throwing Error "Invalid cross-thread access."
}

步骤4 =>尝试绑定Busy指示器

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.ComponentModel;
using System.Windows.Threading;


namespace SilverlightApplication2
{
    public partial class MainPage : INotifyPropertyChanged
    {
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        public const string IsBusyPropertyName = "busyIndicator1";
        private bool _isBusy = false;
        public bool IsBusy
        {
            get
            {
                return _isBusy;
            }
            set
            {
                if (_isBusy != value)
                {
                    _isBusy = value;
                    RaisePropertyChanged(IsBusyPropertyName);
                }
            }
        }

        protected void RaisePropertyChanged(string propertyName)
        {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if ((propertyChanged != null))
            {
                propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {

            IsBusy = true;

            test1();

            IsBusy=false;

        }

    }


    public partial class MainPage : UserControl
    {

        public MainPage()
        {
            InitializeComponent();



        }


        private void test1()
        {


            for (int i = 1; i < 10000; i++)
            {
                System.Diagnostics.Debug.WriteLine(i.ToString());
            }


        }



    }
}

注意:-我想要一个解决方案,它应该在silverlight中的Web表单中工作,而不是在windows窗体中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-23 11:08:44

这应该对你有用。本质上,将处理代码放在线程中,然后通过Dispatcher返回您的UI控件。

代码语言:javascript
复制
 public partial class MainPage : UserControl
    {
        private Thread _thread1;

        public MainPage()
        {
            InitializeComponent();
        }

        private void StartThreads()
        {
            _thread1 = new Thread(test1);
            _thread1.Start();
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            busyIndicator1.IsBusy = true;
            StartThreads();
        }

        private void test1()
        {
            for (int i = 1; i < 10000; i++)
            {
                System.Diagnostics.Debug.WriteLine(i.ToString());
            }
            this.Dispatcher.BeginInvoke(delegate()
            {
                textBox1.Text = "test";
                busyIndicator1.IsBusy = false;
            });
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2011-11-23 10:26:08

之所以会出现此错误,是因为UI方法只能在UI (也称为Dispatcher)线程上调用。要克服在另一个线程上执行UI操作的要求,您应该调用主UI线程上的操作。(见下文)

内联调用

代码语言:javascript
复制
// Disable some control
this.Dispatcher.BeginInvoke(new Action(() => this.SomeControl.IsEnabled = false));

方法驱动的调用

代码语言:javascript
复制
private void SomeMethodRunningOnAnotherThread()
{
    // ... perform some operations

    // Update the UI
    UpdateUI();

    // ... perform more operations
}

private void UpdateUI()
{
    // Make sure we're running on the UI thread
    if (!CheckAccess())
    {
        this.Dispatcher.BeginInvoke(new Action(UpdateUI));
        return;
    }

    // Disable some control
    this.SomeControl.IsEnabled = false;
}

在大多数情况下,第二种方法可能更好--特别是在执行多个UI操作时。值得注意的是,一旦UI线程处于空闲状态,这些UI操作将在UI线程上执行,因此,如果您已经在执行其他操作,您将不会看到更新。此外,通过使用BeginInvoke,您不会阻塞调用线程。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8240490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档