我想从类中的进程线程事件触发器更改Form控件属性,我有以下代码但是我收到了这个例外:
调用线程因为不同而无法访问此对象 线程拥有它。
代码:
public partial class main : Window
{
public main()
{
InitializeComponent();
}
public void change()
{
label1.Content = "hello";
}
private void button1_Click(object sender, RoutedEventArgs e)
{
nmap nmap = new nmap(this);
nmap.test("hello");
}
}
class nmap
{
private main _frm;
private Process myprocess;
public nmap(main frm)
{
_frm = frm;
}
public void test(object obj)
{
string s1 = Convert.ToString(obj);
ProcessStartInfo startInfo = new ProcessStartInfo();
myprocess = new Process();
myprocess.StartInfo.FileName = "C:\\nmap\\nmap.exe";
myprocess.EnableRaisingEvents = true;
myprocess.Exited += new EventHandler(myProcess_Exited);
myprocess.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
try
{
_frm.change();
}
catch{}
}
}
请帮助我,我认为委托调用必须是工作
我的项目是一个WPF C#项目。
答案是:class nmap
{
private main _frm;
private Process myprocess;
public nmap()
{
}
public nmap(main frm)
{
_frm = frm;
}
public void test(object obj)
{
string s1 = Convert.ToString(obj);
ProcessStartInfo startInfo = new ProcessStartInfo();
myprocess = new Process();
myprocess.StartInfo.FileName = "C:\\nmap\\nmap.exe";
//myprocess.StartInfo.CreateNoWindow = true;
myprocess.EnableRaisingEvents = true;
//myprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
myprocess.Exited += new EventHandler(myProcess_Exited);
myprocess.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
try
{
String s;
s = "hello";
_frm.Dispatcher.Invoke(_frm.USD, new Object[] { s });
}
catch{}
}
}
public partial class main : Window
{
public delegate void UpdateStatusDelegate(string value);
public UpdateStatusDelegate USD;
public main()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
USD = new UpdateStatusDelegate(this.AddString);
}
private void AddString(String s)
{
label1.Content = s;
}
public void change()
{
label1.Content = "hello";
}
private void button1_Click(object sender, RoutedEventArgs e)
{
nmap nmap = new nmap(this);
nmap.test("hello");
}
}
答案 0 :(得分:2)
您不能从拥有该对象的线程以外的任何线程触摸任何UI元素。为此,您可以将调用包装在这样的Invoke方法中:
delegate void UpdateStatusDelegate (string value);
private void UpdateStatus(string value)
{
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new UpdateStatusDelegate(UpdateStatus), new object[]{value});
return;
}
// Must be on the UI thread if we've got this far
statusIndicator.Text = value;
}
在WPF世界中,你可以通过使用Dispatcher.Invoke方法获得相同的东西。
答案 1 :(得分:0)
在您的公共虚空更改方法上尝试此操作:
public void change(string text)
{
if (label1.InvokeRequired)
{
var a = new Action<string>(change);
this.Invoke(a, new object[] { text });
}
else
{
label1.Content = "hello";
}
}
取自http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx稍加修改以适合您的问题。我建议你在那里阅读,以便了解正在发生的事情
答案 2 :(得分:0)
您必须在UI线程上调用该方法。使用此代码:
public partial class main : Window
{
//...
public void change()
{
if(Dispatcher.Thread.ManagedThreadId == Thread.ManagedThreadId)
{
// The method was called within the UI thread
label1.Content = "hello";
}
else
{
// The method was called from different thread and we need to call Invoke
var callback = new Action(change);
Dispatcher.Invoke(callback);
}
}
//..
}
答案 3 :(得分:0)
您只需对myProcess_Exited函数进行微小更改,以便在主(UI)线程上进行调用:
private void myProcess_Exited(object sender, System.EventArgs e)
{
Application.Current.Dispatcher.BeginInvoke(() => {
_frm.change();
});
}