简体   繁体   English

通过MEF导出类时如何正确退出带有循环的后台线程?

[英]How to properly exit background thread with loop when class exported via MEF?

I implemented class that serves as TcpCLient server. 我实现了充当TcpCLient服务器的类。 Looks like this: 看起来像这样:

{

[Export]
public class MessageListener
{
    private readonly TcpListener tcpListener;
    private readonly Thread listenThread;

    private DataRepository DataRepository { get; set; }

    private IEventAggregator EventAggregator { get; set; }

    [ImportingConstructor]
    public MessageListener(DataRepository dataRepository, IEventAggregator eventAggregator)
    {
        this.DataRepository = dataRepository;
        this.EventAggregator = eventAggregator;

        // TODO: Need to put proper Port number
        this.tcpListener = new TcpListener(IPAddress.Any, 3000);
        this.listenThread = new Thread(this.ListenForClients);
        this.listenThread.Start();
    }

    private void ListenForClients()
    {
        this.tcpListener.Start();

        while (true)
        {
            // blocks until a client has connected to the server
            var client = this.tcpListener.AcceptTcpClient();

            // create a thread to handle communication with connected client
            var clientThread = new Thread(this.HandleClientComm);
            clientThread.Start(client);
        }
    }

This listener imported in my Shell view model. 此侦听器已导入我的Shell视图模型中。 Works good. 效果不错。

When I close WPF window - MEF won't dispose this object. 当我关闭WPF窗口时-MEF不会处理该对象。 Windows closes but process still running. Windows关闭,但进程仍在运行。 How do I properly shutdown this "server"? 如何正确关闭此“服务器”? It waits for var client .. 等待var client ..

The process won't exit until all foreground threads complete. 在所有前台线程完成之前,该过程不会退出。

In this case, since you're starting a new thread, you can just make it a background thread: 在这种情况下,由于您正在启动新线程,因此可以将其设为后台线程:

this.listenThread = new Thread(this.ListenForClients);
this.listenThread.IsBackground = true;
this.listenThread.Start();

Background threads won't keep the process alive. 后台线程将无法使进程继续运行。

Mark your class as implementing IDisposable , and set a disposed flag in the Dispose implementation. 你的类为实现IDisposable ,并设置一个disposed中旗Dispose实施。 Then change your loop where you accept connections like this: 然后更改您接受连接的循环,如下所示:

    while (!this.disposed)
    {
        Thread.Sleep(1); // to avoid spinning a core 100%
        if (this.tcpListener.Pending)
        {
            // shouldn't block because we checked tcpListener.Pending
            var client = this.tcpListener.AcceptTcpClient();
            var clientThread = new Thread(this.HandleClientComm);
            clientThread.Start(client);
        }
    }

MEF will take care of calling Dispose on any disposable components it created, provided that you dispose the MEF container itself when the application exits. MEF将负责在其创建的任何一次性组件上调用Dispose ,前提是您在应用程序退出时自行处置MEF容器。

It doesnt stop because of the infinite loop. 它不会因无限循环而停止。 You need to use a flag, a mutex or something like that, so that the loop stops and the thread will return and stop properly. 您需要使用一个标志,一个互斥锁或类似的东西,以便循环停止并且线程将正确返回并停止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM