R
Ragnar
Hi guys. Just wanted to share an interesting problem:
I am polling a web service for changes in db, so I
created different threads for different tasks
(functions). All querying the same web service.
First I decided to use the same web servcie stub from all
threads. But then I noticed that the application was
building up memory and never releasing it although
everything was Disposed() of and GC.Collect().
After a lot of trial and error I found out that if I
omitted the assignment of CredentialCache to
mywebservice.Credentials the problem went away. I am
using Basic Authentication for now.
Thats nice but I really needed the Credential mechanism
so I did some more experiments.
What I found out is that I must create a new instance of
web service sink in each thread and assign it its
credentials from within that same thread. Furthermore if
the thread function is in an object , and that object is
a member variable in parent object that has the same
webservice sink object as a member as well, memory
accumulation starts again...
This took quite a while to realize, has anyone got a
suggestion for this behaviour?
Cheers,
Raggi
Code snipped from a little test program:
[STAThread]
static void Main(string[] args)
{
job j = new job();
j.Start();
Console.ReadLine();
j.Stop();
}
class job
{
protected MyWebService s = null;
protected Thread WorkerThread;
protected Thread WorkerThread2;
public void Start()
{
s = new MyWebService();
//Comment following line in for
endless memory buildup
//s.Credentials =
Util.GetCredentials();
Worker w = new Worker();
WorkerThread = new Thread(new
ThreadStart(w.DoStuff));
WorkerThread.Start();
Worker2 w2 = new Worker2();
WorkerThread2 = new Thread(new
ThreadStart(w2.DoStuff));
WorkerThread2.Start();
}
public void Stop()
{
WorkerThread.Abort();
WorkerThread2.Abort();
}
}
public class Worker
{
public void DoStuff()
{
int i = 0;
MyWebService s = new MyWebService
();
s.Credentials =
Util.GetCredentials();
while(true)
{
DataSet
TempActivityStatus = s.GetCurrentState(24);
foreach(DataRow row in
TempActivityStatus.Tables[1].Rows)
{
Console.WriteLine
(row[1].ToString() + i);
}
TempActivityStatus.Clear
();
TempActivityStatus.Dispose
();
TempActivityStatus = null;
GC.Collect();
i++;
Thread.Sleep(10);
}
}
}
public class Util
{
public static CredentialCache
GetCredentials()
{
// Create a new instance of
CredentialCache.
CredentialCache credentialCache =
new CredentialCache();
// Create a new instance of
NetworkCredential using the client credentials.
NetworkCredential credentials =
new NetworkCredential("MyWebServiceUser","123","Domain");
// Add the NetworkCredential to
the CredentialCache.
credentialCache.Add(new Uri
("http://mycomp/MyWebService/MyWebService.asmx"), "Basic",
credentials);
// Add the CredentialCache to the
proxy class credentials.
return credentialCache;
}
}
I am polling a web service for changes in db, so I
created different threads for different tasks
(functions). All querying the same web service.
First I decided to use the same web servcie stub from all
threads. But then I noticed that the application was
building up memory and never releasing it although
everything was Disposed() of and GC.Collect().
After a lot of trial and error I found out that if I
omitted the assignment of CredentialCache to
mywebservice.Credentials the problem went away. I am
using Basic Authentication for now.
Thats nice but I really needed the Credential mechanism
so I did some more experiments.
What I found out is that I must create a new instance of
web service sink in each thread and assign it its
credentials from within that same thread. Furthermore if
the thread function is in an object , and that object is
a member variable in parent object that has the same
webservice sink object as a member as well, memory
accumulation starts again...
This took quite a while to realize, has anyone got a
suggestion for this behaviour?
Cheers,
Raggi
Code snipped from a little test program:
[STAThread]
static void Main(string[] args)
{
job j = new job();
j.Start();
Console.ReadLine();
j.Stop();
}
class job
{
protected MyWebService s = null;
protected Thread WorkerThread;
protected Thread WorkerThread2;
public void Start()
{
s = new MyWebService();
//Comment following line in for
endless memory buildup
//s.Credentials =
Util.GetCredentials();
Worker w = new Worker();
WorkerThread = new Thread(new
ThreadStart(w.DoStuff));
WorkerThread.Start();
Worker2 w2 = new Worker2();
WorkerThread2 = new Thread(new
ThreadStart(w2.DoStuff));
WorkerThread2.Start();
}
public void Stop()
{
WorkerThread.Abort();
WorkerThread2.Abort();
}
}
public class Worker
{
public void DoStuff()
{
int i = 0;
MyWebService s = new MyWebService
();
s.Credentials =
Util.GetCredentials();
while(true)
{
DataSet
TempActivityStatus = s.GetCurrentState(24);
foreach(DataRow row in
TempActivityStatus.Tables[1].Rows)
{
Console.WriteLine
(row[1].ToString() + i);
}
TempActivityStatus.Clear
();
TempActivityStatus.Dispose
();
TempActivityStatus = null;
GC.Collect();
i++;
Thread.Sleep(10);
}
}
}
public class Util
{
public static CredentialCache
GetCredentials()
{
// Create a new instance of
CredentialCache.
CredentialCache credentialCache =
new CredentialCache();
// Create a new instance of
NetworkCredential using the client credentials.
NetworkCredential credentials =
new NetworkCredential("MyWebServiceUser","123","Domain");
// Add the NetworkCredential to
the CredentialCache.
credentialCache.Add(new Uri
("http://mycomp/MyWebService/MyWebService.asmx"), "Basic",
credentials);
// Add the CredentialCache to the
proxy class credentials.
return credentialCache;
}
}