-1

So after a long time of cursing and giving up hope I got everything to work (almost).

I have a GUI which displays a list of connected addresses and a list of messages. Normally when I close a connector (disconnect from an address) I write a message saying: "disconnected from address x". However as you will see from the methods, when disposing the application I cannot use the dispatcher to write that message (this.ModuleConnections.Remove(address); triggers the writing of the message and also removes it visually from the list).

private void CloseConnector(string address)
{
    Task task = new Task(() =>
    {
        var moduleConnection = this.ModuleConnections[address];
        moduleConnection.ModuleConnector.Dispose();

        if (mDisposed == true)
        {
            ApplicationSupport.Dispatcher.Invoke(
                DispatcherPriority.Background,
                new Action(() =>
                {
                    this.ModuleConnections.Remove(address);
                }));
        }
    });

    task.Start();
    if (mDisposed == true)
    {
        mTasks.Add(task);
    }
}

protected virtual void Dispose(bool disposing)
{
    // Dispose managed resources.
    if ((mDisposed == false) && (disposing == true))
    {
        mTasks.Clear();
        mDisposed = true;
        CloseConnectors();
        Task.WaitAll(mTasks.ToArray());
    }
}

I cannot use the dispatcher because Task.WaitAll stops the thread. If the thread is stopped the dispatcher cannot execute this.ModuleConnections.Remove(address); and this results in the task not finishing, if the tasks not finish Task.WaitAll won't release the thread. Which is a very big problem.

Without the task.waitall i would get a tremendous amount of object disposed and key not found exceptions and other nasty things which kept some threads running and thus the application wouldn't shut down completely.

But now, when it closes, the GUI freezes (looks like it crashed) for a few seconds and then (when task.waitall is finished) it closes the window and the entire application is closed correctly.

What I want is to still be able to update my list of messages and display what addresses have disconnected.

Just to clarify
I need the Task in the CloseConnector method because closing the connector (dispose) makes it disconnect, it needs to wait until it receives a message back from the other side before the code continues. if i were to run this 1 by one it would take minutes, in parallel as i do it now it only takes a few seconds.

Vincent
  • 1,497
  • 1
  • 21
  • 44
  • May i ask why this is downvoted, have i formulated the question wrong? should i not ask these questions? what's wrong? why do people never tell you what's wrong :( – Vincent Nov 16 '15 at 15:48
  • I don't know about that, but I do think providing an [MCVE](http://stackoverflow.com/help/mcve) will help. – Pieter Witvoet Nov 16 '15 at 16:05
  • @PieterWitvoet thanks pieter, I will try to add it when i have a bit more time :) – Vincent Nov 16 '15 at 16:08

1 Answers1

0

First thing that I saw that you do not need to call Start() method for your task if you want to tun them all with WaitAll() menthod. Also if you want to run one task at a time, its better to use Task.Run() which takes Expression as an argument. The difference in this case is that Run() forces your task to start immediately while Start() can not guarantee that your task will be started now - it's just plan it to start with TaskScheduler. By the way, Wait() work in the same way

Finally, check your this object - what is this at this time? Is it not null? Maybe try to use closure and take your dispatcher as an arg

Hope that helps

Andrew
  • 1,474
  • 4
  • 19
  • 27
  • There is no Task.Run(). I call task.run for when i'm not disposing because then there is no need to wait for the tasks to finish. did not know task.waitall starts the tasks as well, might put a if(mDisposed == false) around the task.start(). the this object is not null, it will never be null because i always instantiate everyhting. what do you mean with closure and my dispatcher as an arg? – Vincent Nov 16 '15 at 15:46
  • Can this work in your case? `ApplicationSupport.Dispatcher.Invoke( DispatcherPriority.Background, (disp) => { disp.ModuleConnections.Remove(address); });` – Andrew Nov 16 '15 at 15:51
  • you can't do that. and it still wouldn't solve the problem – Vincent Nov 16 '15 at 16:00