2012-05-21 148 views
1

我想改变进程线程事件火灾窗体控件属性中,我有以下的代码,但我收到此异常类:委托调用

调用线程不能访问此对象,因为不同的 线程拥有它。

代码:

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"); 

     } 
} 

回答

2

不能从除拥有该对象的线程以外的任何线程接触任何UI元素。要做到这一点,你可以在调用方法这样换电话:

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方法得到同样的事情。

+0

嗨哈迪我在WPF工作没有InvokeRequired方法,但无论如何,我仍然有这个问题!请描述更多谢谢! –

+0

我应该在nmap类或主窗口窗体中使用delegete调用? –

+0

啊,你没有注意到你提到你在使用WPF。在WPF中,您应该能够使用Dispatcher.Invoke方法(几乎)执行相同的操作。 –

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采取稍作修改,以适应您的问题。我建议您在那里阅读,以便了解发生了什么

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

因此调用主(UI)线程时你只需要你的myProcess_Exited功能的微小变化:

private void myProcess_Exited(object sender, System.EventArgs e) 
{ 
    Application.Current.Dispatcher.BeginInvoke(() => { 
     _frm.change(); 
    }); 
}