C#如何从另一个线程的主UI线程在关闭Windows窗体 [英] C# How to close a windows form on the main UI thread from another thread

查看:889
本文介绍了C#如何从另一个线程的主UI线程在关闭Windows窗体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建一个WPF MVVM应用。我有一个漫长的过程,我想在另一个线程同时显示一个繁忙指示用户运行。我的问题如下:



BusyIndi​​cator控件的IsBusy属性绑定到我的视图模式,它实现INotifyPropertyChanged接口的IsBusy公共财产。如果我运行下面的加入代码,然后作为主UI线程等待线程T来完成用户界面不显示繁忙指示器。如果我删除了,然后一起被托管的WPF Windows窗体关闭为时尚早。我知道,在线程访问Windows窗体是一个很大的不,不,但因为所有我想要做的就是接近我想最简单的解决方案的形式是移动_hostForm.Close()的DoLongProcess方法的末尾。当然,如果我这样做,我得到一个跨线程异常。你可以请建议采取在这种情况下,最好的办法?

 < extToolkit:BusyIndi​​cator控件IsBusy ={绑定路径= IsBusy}> 
<! - 在这里有些控件 - >
< / extToolkit:BusyIndi​​cator控件>

私人无效DoSomethingInteresting(){

//设置IsBusy属性设置为true时触发的
//通知属性更改事件
IsBusy = TRUE ;

//做一些事情,需要很长的时间
线程t =新主题(DoLongProcess);
t.Start();
t.Join();

//我们就大功告成了。关闭Windows窗体
IsBusy = FALSE;
_hostForm.Close();

}


解决方案

最好的在这种情况下做的事情,就是在你真正调用形式结束,你通知所有的系统你要关闭,这将给你在结束时运行的任何进程的机会。当你再完成并想从另一个线程关闭窗体,您需要使用调用它的UI线程上:

  _hostForm.BeginInvoke(新动作(()=> _hostForm.Close())); 



这可能会更好,如果你很可能永远从另一个线程关闭窗体,实际创建close方法的线程安全的版本;即:

 公共类MyForm的:表格
{
// ...

酒店的公共空间SafeClose()
{
//确保我们的UI线程
如果运行(this.InvokeRequired)
{
的BeginInvoke(新的Action(SafeClose));
的回报;
}

//现在关闭的形式,我们正在对UI线程
关闭所有正在运行();
}

// ...
}

使用这种方法,您可以继续更新的形式和它的用户界面,同时运行的异步操作,然后调用关闭和清理,当你完成。


I'm creating a WPF MVVM application. I have a long process that I want to run in another thread whilst displaying a busy indicator to the user. The problem I have is as follows:

The IsBusy property of the BusyIndicator control is bound to the IsBusy public property of my view model which implements the INotifyPropertyChanged interface. If I run the code below with the Join then the user interface doesn't show the busy indicator as the main UI thread is waiting for the thread "t" to finish. If I remove the join then the Windows Form which is hosting the WPF closes too early. I know that accessing Windows Forms across threads is a big no no but as all I want to do is close the Form I figure the most simple solution is to move _hostForm.Close() to the end of the "DoLongProcess" method. Of course if I do that I get a cross threading exception. Can you please suggest the best approach to take in this situation?

<extToolkit:BusyIndicator IsBusy="{Binding Path=IsBusy}" >
    <!-- Some controls here -->
</extToolkit:BusyIndicator>

private void DoSomethingInteresting() { 

        //  Set the IsBusy property to true which fires the 
        //  notify property changed event
        IsBusy = true;

        //  Do something that takes a long time
        Thread t = new Thread(DoLongProcess);
        t.Start();
        t.Join();

        //  We're done. Close the Windows Form
        IsBusy = false;
        _hostForm.Close();

    }

解决方案

The best thing to do in this situation, is before you actually invoke the closing of the form, you notify all your systems you are going to close, which will give you the opportunity to run any process at the end. When you are then finished and want to close the form from the other thread, you will need to call it on the UI thread using:

_hostForm.BeginInvoke(new Action(() => _hostForm.Close()));

It might be better, if you are likely to always close the form from another thread, to actually create a thread-safe version of the close method; i.e.:

public class MyForm : Form
{
    // ...

    public void SafeClose()
    {
        // Make sure we're running on the UI thread
        if (this.InvokeRequired)
        {
            BeginInvoke(new Action(SafeClose));
            return;
        }

        // Close the form now that we're running on the UI thread
        Close();
    }

    // ...
}

Using this sort of approach, you can continue to update the form and it's UI while running asynchronous operations, then invoke the shutdown and cleanup when your done.

这篇关于C#如何从另一个线程的主UI线程在关闭Windows窗体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆