Недопустимый доступ между потоками.ошибка - PullRequest
0 голосов
/ 23 ноября 2011

У меня есть веб-форма в серебристом свете.

При нажатии какой-либо кнопки я хочу обновить другой элемент управления, например диаграмму, текстовое поле и т. Д.

В то же время, когда он заполняет диаграммуили текстовое поле, мне нужно показать индикатор занятости

  1. Индикатор занятости должен отображаться первым на экране
  2. за значением графика должно появиться обновление
  3. Значение диаграммы будет отображаться вscreen
  4. Индикатор занятости должен скрываться

Но проблема в том, что когда я пытаюсь использовать нить, я получаю сообщение об ошибке «Недопустимый межпоточный доступ.».Как поток получает доступ к элементу управления пользовательского интерфейса.Вот 4 шага, которые я попробовал:

Любое ценное предложение, как решить эту проблему.

Шаг 1 => Пробная тема

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

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 => Попытался вызвать Событие из кода

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 => Попытался связать Busyindicator

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, а не в форме Windows

Ответы [ 2 ]

3 голосов
/ 23 ноября 2011

Причина, по которой вы получаете эту ошибку, заключается в том, что методы пользовательского интерфейса могут вызываться только в потоке пользовательского интерфейса (также известном как Dispatcher).Чтобы преодолеть это при желании выполнить операции пользовательского интерфейса в другом потоке, вы должны вызвать действие в основном потоке пользовательского интерфейса.(См. Ниже)

Встроенный вызов

// Disable some control
this.Dispatcher.BeginInvoke(new Action(() => this.SomeControl.IsEnabled = false));

Метод-управляемый вызов

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;
}

В большинстве случаеввторой подход может быть лучше - особенно при выполнении нескольких операций пользовательского интерфейса.Стоит отметить, что эти действия пользовательского интерфейса будут выполняться в потоке пользовательского интерфейса после того, как поток пользовательского интерфейса станет бездействующим, поэтому, если вы уже держите его, делая что-то еще, вы не увидите обновления.Также, используя BeginInvoke, вы не задерживаете вызывающую нить.

2 голосов
/ 23 ноября 2011

Это должно работать для вас.По сути, поместите ваш код обработки в поток и верните элемент управления пользовательского интерфейса с помощью диспетчера

 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;
            });
        }
    }
...