Sign in to follow this  

[.net] Multi-threading web services in C#

This topic is 4384 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently developing an app for work which is to be used to test the connectivity to web services in order to verify new environment builds. This section of it is working correctly, however there is over 2000 web methods that need to be tested and this takes around an hour to execute. I'm hoping to cut down this time by multi-threading my app but am not having too much success with it (haven't done this sort of coding since university). I have managed to get basic threading working with just using the Thread.Sleep() method however when trying to convert this logic to invoking web methods I am not seeing any performance gain. This is my current code:
public class Form1 : System.Windows.Forms.Form
{
	DateTime d1, d2;
	TimeSpan ts;
	int nItem, nThreads;
	ThreadStart asdf = null;

	public Form1()
	{
		nItem = 0;
		nThreads = 0;
		asdf = new ThreadStart(ThreadFunc);
		InitializeComponent();
	}

	private void cmdExecuteThreaded_Click(object sender, System.EventArgs e)
	{
		d1 = DateTime.Now;
		nItem = 0;
		listView1.Items.Clear();
		nThreads = 5;
		Thread t1 = new Thread(asdf);
		t1.Name = "asdf1";
		t1.Start();
		Thread t2 = new Thread(asdf);
		t2.Name = "asdf2";
		t2.Start();
		Thread t3 = new Thread(asdf);
		t3.Name = "asdf3";
		t3.Start();
		Thread t4 = new Thread(asdf);
		t4.Name = "asdf4";
		t4.Start();
		Thread t5 = new Thread(asdf);
		t5.Name = "asdf5";
		t5.Start();
	}

	public void ThreadFunc()
	{
		string strMethod = "", strFilename = "", strURL = "", strResult = "";
		Monitor.Enter(this);
		strMethod = cboMethods.Items[nItem].ToString();
		strFilename = "Data\\test.asmx - " + strMethod + ".txt";
		strURL = "http://testurl/test.asmx";
		strResult = InvokeService(strFilename, strURL, strMethod);
		LoadViewList(strResult);
		nItem++;
		Monitor.Exit(this);
		if (nItem < cboMethods.Items.Count - 4)
		{
			Thread tNew = new Thread(asdf);
			tNew.Name = Thread.CurrentThread.Name;
			tNew.Start();
			nThreads++;
		}
		nThreads--;
		if (nThreads == 0)
		{
			ThreadFuncDone();
		}
	}

	public void ThreadFuncDone()
	{
		d2 = DateTime.Now;
		ts = d2 - d1;
		MessageBox.Show(ts.TotalSeconds.ToString());
	}

	public void LoadViewList(string strData)
	{
		string[] arrData = strData.Split('$');
		ListViewItem item = new ListViewItem(arrData[0]);
		item.SubItems.Add(arrData[1]);
		item.SubItems.Add(arrData[2]);
		item.SubItems.Add(arrData[3]);
		item.SubItems.Add(arrData[4]);
		listView1.Items.Add(item);
	}

	public string InvokeService(string strFilename, string strService, string strMethod)
	{
		string strResult = "";
		try
		{
			//Generate XML request here...
			strResult = "PASS$" + strService + "$" + strMethod + "$" + "Execution Status$" + currentNode.text;
		}
		catch (Exception e)
		{
			strResult = "FAIL$" + strService + "$" + strMethod + "$" + "Exception$" + e.Message + " - " + e.ToString();
		}
		return strResult;
	}
}

Any ideas where this is going wrong?

Share this post


Link to post
Share on other sites
Instead of mucking about with manually creating threads, why don't you invoke the web methods asynchronously? For each web method Foo() that's generated by the proxy generator, there should be an equivalent asynchronous method, FooAsync(), accompanied by a FooCompleted() event.

Share this post


Link to post
Share on other sites
Because of the "Monitor.Enter(this);" you push all threads but one in a waiting queue (as far as I can see)

Are you sure you are profiling the right part? When the web service is slow this won't help.

And btw: don't access form-controls on a different thread than the thread they were created on.

cheers

Share this post


Link to post
Share on other sites
Well I've tried moving the Monitor.Enter/Exit around and it seems to work. My code now looks like this:


//MessageBox.Show("pre");

Monitor.Enter(this);
strMethod = cboMethods.Items[nItem].ToString();
nItem++;
strFilename = "Data\\test.asmx - " + strMethod + ".txt";
strURL = "http://testurl/test.asmx";
Monitor.Exit(this);

strResult = InvokeService(strFilename, strURL, strMethod);
LoadViewList(strResult);

//MessageBox.Show("post");

The problem that I have now is that my five initial threads are started and simply seem to hang doing nothing. However if I uncomment the "pre" & "post" message boxes it all seems to run correctly. Any way of getting this running without the message boxes in place as it's not going to be practical having to click 4000 of them?

Share this post


Link to post
Share on other sites
you are still accessing controls on threads other than the creating thread! By showing the messagebox you boost the creating thread and thus 'unlock' the executing thread. In LoadListview use this.Invoke(...) instead of directly modifying the listview.

Cheers

Share this post


Link to post
Share on other sites

This topic is 4384 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this