无效的跨线程访问。错误
我有一个 silverlight 网络表单。
单击某个按钮的操作时,我想更新另一个控件,如图表、文本框等。
在它填充图表或文本框的同时,我需要显示一个繁忙指示器,
- 繁忙指示器应首先显示在屏幕上,
- 图表值后面应该显示更新
- 图表值将反映在屏幕上
- 忙碌指示器应该隐藏
但问题是当我尝试使用线程时我收到错误“无效的跨线程访问”。当线程访问时 用户界面控件。我尝试过的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 中以 Web 形式而不是 Windows 形式工作的解决方案
I have a web form in silverlight.
On action of some button click i want to update a another control like chart, Textbox etc
In the mean time when it fills the chart or textbox, i need to show a busy indicator
- Busy indicator should show first in screen
- behind the chart value should get update
- Chart value will reflect in screen
- Busy indicator should hide
But the problem is when i try using Thread I am getting an error "Invalid cross-thread access.". As the thread is accessing
the UI control. The 4 steps which i have tried is as follows.
Any valuable suggestion how to solve this issue.
Step 1 => Tried Thread
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();
}
}
}
step 2 => Tried 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();
}
}
}
Step 3 => Tried to raise an Event from the code behind
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."
}
step 4 => Tried Binding the 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());
}
}
}
}
Note:- I want a solution which should work in Web form in silverlight not the windows form
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您收到此错误的原因是 UI 方法只能在 UI(又名 Dispatcher)线程上调用。为了在想要在另一个线程上执行 UI 操作时克服这个问题,您应该在主 UI 线程上调用该操作。 (见下文)
内联调用
方法驱动的调用
在大多数情况下,第二种方法可能更好 - 特别是在执行多个 UI 操作时。值得注意的是,一旦 UI 线程空闲,这些 UI 操作将在 UI 线程上执行,因此,如果您已经暂停执行其他操作,则将看不到更新。另外,通过使用BeginInvoke,您不会阻塞调用线程。
The reason you are getting this error is because UI methods can only be invoked on the UI (aka Dispatcher) thread. To overcome this when wanting to perform UI operations on another thread, you should invoke the action on the main UI thread. (See below)
Inline Invocation
Method-Driven Invocation
In most cases, the second approach may be better - particularly when performing multiple UI operations. It is worth noting that these UI actions will be executed on the UI thread once the UI thread has become idle, so if your already holding it up doing something else, you won't see the update. Also, by using
BeginInvoke
you don't hold up the calling thread.这应该对你有用。本质上是将您的处理代码放在一个线程中,并通过调度程序取回您的 UI 控制
This should work for you. Essentially place your processing code in a thread and get back your UI control via a Dispatcher