我在silverlight有一个网页表格。
单击某个按钮的操作时,我想更新另一个控件,如图表、文本框等。
同时,当它填充图表或文本框时,我需要显示一个繁忙的指示器。
但问题是,当我尝试使用线程时,我得到了一个错误“无效的跨线程访问”。当线程正在访问UI控件时。我尝试过的四个步骤如下。
任何有价值的建议如何解决这个问题。
步骤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 =>尝试绑定Busy指示器
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窗体中。
发布于 2011-11-23 11:08:44
这应该对你有用。本质上,将处理代码放在线程中,然后通过Dispatcher返回您的UI控件。
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;
});
}
}发布于 2011-11-23 10:26:08
之所以会出现此错误,是因为UI方法只能在UI (也称为Dispatcher)线程上调用。要克服在另一个线程上执行UI操作的要求,您应该调用主UI线程上的操作。(见下文)
内联调用
// 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;
}在大多数情况下,第二种方法可能更好--特别是在执行多个UI操作时。值得注意的是,一旦UI线程处于空闲状态,这些UI操作将在UI线程上执行,因此,如果您已经在执行其他操作,您将不会看到更新。此外,通过使用BeginInvoke,您不会阻塞调用线程。
https://stackoverflow.com/questions/8240490
复制相似问题