Click here to Skip to main content
15,884,537 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi fellow Code Project coders

I have a WCF service, consumed by a Silverlight application that, for testing purposes, handles callbacks and a CallbackChannel client list for a small testing chat application.

I was running into some problems in the main application I’m working on and mighty Google told me that I needed to implement multithreading.

Ok, multithreading it is! Let’s test it.

After some changes on my service I’ve got a stable solution working on my developing environment that goes like this:

C#
[OperationContract]
public void Publish(string message)
{
    lock (clients)
    {
        foreach (IDBNotificationCallbackContract channel in clients)
        {
            Thread t = new Thread(new ParameterizedThreadStart(this.notifyClient));
            t.Start(new Callback_info { CallBackContract = channel, Message = DateTime.Now.ToString() + "\n" + message }); 
        }
    }
}

void notifyClient(Object n)
{
    Callback_info notif = (Callback_info)n;
    try
    {
        if ((notif.CallBackContract as ICommunicationObject).State == CommunicationState.Opened)
            notif.CallBackContract.Notify(notif.Message);
    }
    catch
    {
    }
}


Although the thread initialization is made inside the foreach cycle, I wondered if it really gets disposed after the thread is completed or am I running into memory and/or processor load troubles if this ever goes to production like this?

If so, how do I dispose the thread? There is no Dispose method in the Thread class neither there is a Completed event to hook up to asynchronously.

The thing is that on my development environment I tried a small stress test and opened 40 browser windows running the test application.

When pressed the button to start bombing messages the machine went nuts for 20 minutes with a 100% load during that time and I’m not sure that the load was from the service or the 40 opened browser windows.

Appreciate any light on this doubt of mine.
Posted
Updated 23-Jan-14 0:44am
v2

1 solution

you don't need to tackle with threads if you are designing a wcf service. wcf services can manage all this kind of stuff for you.
I advice you to look at this great article. WCF Concurrency (Single, Multiple, and Reentrant) and Throttling[^]

and I think you need to configure your wcf service as
VB
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession,
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
 
Share this answer
 
Comments
Jorge J. Martins 23-Jan-14 8:10am    
The ServiceBehavior is configured that way.

The real problem is when a user closes the browser or a network problem arises, the service, being synchronous, hangs for about a minute tryig to callback the unexistent client and all subsequent notificaions are delayed.

That's why I went to multithreading. This way, each notification uses a diferent thread and doesn't interfere with the rest of the notifications to be sent.

And it works great this way.

P.S. I think WCF handles well, as You said, but it aplies to Requests. Here I I'm dealing with Callbacks.
Vedat Ozan Oner 23-Jan-14 8:55am    
Ok, then maybe you can use process explorer to see resource usage by your service. http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
a thread is a OS resource and managed by runtime. when you run a code, a thread is reserved for it to get processor time. therefore, it is returned to OS when your code execution is completed. therefore, dispose or completed things becomes unnecessary. at least, I think so :)
Vedat Ozan Oner 23-Jan-14 8:59am    
one more thing. you can use ThreadPool to feel better about performance. http://msdn.microsoft.com/en-us/library/system.threading.threadpool%28v=vs.110%29.aspx
Jorge J. Martins 23-Jan-14 9:58am    
This ThreadPool hint was great for I discovered a 200 thread limit on my machine.

On my stress tests i fired around 4000 notifications meaning 4000 threads on the system!

With TreadPool I've rewriten my code and replaced:

Thread t = new Thread(new ParameterizedThreadStart(this.notifyClient));

t.Start(new Callback_info { CallBackContract = channel, Message = DateTime.Now.ToString() + "\n" + message });

with:

ThreadPool.QueueUserWorkItem(this.notifyClient, new Client_info { CallBackContract = channel, Message = DateTime.Now.ToString() + "\n" + message });

It's still working and I don't have to bother about disposing.Thanks
Vedat Ozan Oner 23-Jan-14 14:34pm    
You are welcome :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900