简体   繁体   中英

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

I implemented class that serves as TcpCLient server. 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. Works good.

When I close WPF window - MEF won't dispose this object. Windows closes but process still running. How do I properly shutdown this "server"? It waits for 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. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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