-2

I have this project in which i am calling a web service, receiving rates from the web service, processing it and displaying it in appropriate text boxes,

As you can guess the waiting for response from web service, and processing is too much work on a single thread, and the app gets unresponsive every once in a while so i had to use multi-theading to make the app more responsive. I am naive to multi-threading and i did something like this: a thread that makes the webservice calls:

Webservicethread = new Thread(() => RefreshRates(marketId1));
            Webservicethread.Start();

this thread in turn calls another thread to do the heavy processing part:

t = new Thread(() => fillData(response.Length - 1, response));
                t.Start();

The problem is that this form is supposed to have a no. of instances running in parallel at the same time, which was working fine untill i tried to apply multithreading in my form,

now that i have tried to multithread it, running a second or a third instance heavily effects the working of all other instances of the app, and it totally freezes after i open the third instance.

I am totally confused what could possibly be done, some1 please help me out here.....:/

the filldata() method extracts the rates from the webservice response and fills them in the respective textboxes

*EDIT

here is my complete code, sorry as it gets too lengthy....

As suggested by Aaleksey, i profiled my code with ANTS profiler, filldata() is consuming even more time than th webservice call.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BetRates_NS.com.betfair.api;
using BetRates_NS.BFExchangeService;
using System.Net;
using System.Threading;

namespace BetRates_NS
{
    public partial class Rates : Form
    {
        public Rates()
        {
            InitializeComponent();
        }
        Thread t;
        Thread Webservicethread;
        private BFGlobalService bfg1 = new BFGlobalService();
        private BFExchangeService.BFExchangeService bfg2 = new BetRates_NS.BFExchangeService.BFExchangeService();
        int marketId1 = 0;
        public int MarketId1
        {
            get { return marketId1; }
            set { marketId1 = value; }
        }
        string match_name="";
        public string Match_name
        {
            get { return match_name; }
            set { match_name = value; }
        }
        string match_date = "";
        public string Match_date
        {
            get { return match_date; }
            set { match_date = value; }
        }
        string sessionToken = "";
        public string SessionToken
        {
            get { return sessionToken; }
            set { sessionToken = value; }
        }
        int max_len = 0;
        public int Max_len
        {
            get { return max_len; }
            set { max_len = value; }
        }
        bool inPlay=false;

        protected override bool ShowWithoutActivation
        {
            get { return true; }
        }
        public void ClearTextBoxes(Control control)
        {
            foreach (Control c in control.Controls)
            {
                if (c is TextBox)
                {
                    ((TextBox)c).Clear();
                }
                if (c.HasChildren)
                {
                    ClearTextBoxes(c);
                }
            }
        }

        private void RefreshRates(int marketid_temp)
        {
            try
            {
                //ClearTextBoxes(this);
                BFExchangeService.APIRequestHeader header2 = new BetRates_NS.BFExchangeService.APIRequestHeader();
                header2.clientStamp = 0;
                header2.sessionToken = sessionToken;

                //**************************** GET PRICES ****************************

                GetMarketPricesCompressedReq price_req1 = new GetMarketPricesCompressedReq();
                price_req1.header = header2;
                price_req1.marketId = marketId1;
                price_req1.currencyCode = "GBP";
                GetMarketPricesCompressedResp price_resp = new GetMarketPricesCompressedResp();
                price_resp = bfg2.getMarketPricesCompressed(price_req1);
                string prices = price_resp.marketPrices;
                string[] Parts = prices.Split(':');
                is_InPlay(Parts[0]);
                t = new Thread(() => fillData(Parts.Length - 1, Parts));
                t.Start();
                //fillData(Parts.Length - 1, Parts);
            }
            catch (Exception ep)
            {
                //MessageBox.Show(ep.Message);
            }
        }

        private void is_InPlay(string temp)
        {
            string[] check = temp.Split('~');
            if (Convert.ToInt32(check[3]) != 0)
            {
                inPlay = true;
                pictureBox2.Visible = true;
                ToolTip t1 = new ToolTip();
                t1.SetToolTip(this.pictureBox2, "InPlay");
            }
            else
            {
                inPlay = false;
                pictureBox2.Visible = false;
            }
        }

        private void Rates_Load(object sender, EventArgs e)
        {
            this.Text = match_name;
            //lbl_match.Text = match_name;
            BFExchangeService.APIRequestHeader header2 = new BetRates_NS.BFExchangeService.APIRequestHeader();
            header2.clientStamp = 0;
            header2.sessionToken = sessionToken;

            GetMarketReq market_req1 = new GetMarketReq();
            market_req1.header = header2;
            market_req1.marketId = Convert.ToInt32(marketId1);
            GetMarketResp market_resp1= bfg2.getMarket(market_req1);
            Market market1 = market_resp1.market;
            Runner[] runners_list = market1.runners;
            makeMyRows(runners_list.Length);
            this.Height=60+(36*runners_list.Length);
            int max_length = 0;
            for (int i = 0; i < runners_list.Length; i++)
            {
                if (max_length < runners_list[i].name.Length)
                {
                    max_length = runners_list[i].name.Length;
                }
                int label_counter = i + 1;
                string ctrl_name = "lbl" + label_counter.ToString();
                Label temp = null;
                foreach (Control ctl in this.Controls)
                {
                    if ((ctl is Label) && (ctl.Name == ctrl_name))
                   { temp = (Label)ctl; }
                }
                if (temp != null)
                { temp.Text = runners_list[i].name; }
            }
            //max_len = max_length;
            //MessageBox.Show(max_len.ToString());
            System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
            myTimer.Interval = 200;
            myTimer.Tick += new EventHandler(myTimer_Tick);
            myTimer.Enabled = true;
            this.Focus();
            if (this.VerticalScroll.Visible == true)
            {
                this.Width = this.Width + 24;
            }
        }

        private void myTimer_Tick(object sender, EventArgs e)
        {
            Webservicethread = new Thread(() => RefreshRates(marketId1));
            Webservicethread.Start();
            //RefreshRates(marketId1);
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            this.Refresh();
            this.RefreshRates(marketId1);
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }




        //public delegate void FillData1(int count1, string[] parts1);
        private void fillData(int count,string[] Parts)
        {
            for (int i = 1; i <= count; i++)
            {
                string[] subParts = Parts[i].Split('|');
                for (int j = 1; j <= subParts.Length-1; j++)
                {
                    string[] Fields = subParts[j].Split('~');
                    for (int k = 1; k <= 6; k++)
                    {
                        string compare_txt = "";
                        string ctrl_name = "txt" + i.ToString() + k.ToString();
                        TextBox temp = null;// = (TextBox)findCtrl(ctrl_name);
                        foreach (Control ctl in this.Controls)
                        {
                            if ((ctl is TextBox) && (ctl.Name == ctrl_name))
                            { temp = (TextBox)ctl; }
                        }
                        if (j == 1)
                        {
                            switch (k)
                            {
                                case 1:
                                    compare_txt = temp.Text;
                                    //temp.Text = "";
                                    temp.Invoke(new AddText1(AddText), new object[] { ctrl_name, "" });
                                    if (Fields.Length >= 9)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[8]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, Fields[8] });
                                            //temp.Text = Fields[8];
                                        }
                                    }
                                    if (Fields.Length >= 10)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[9]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, temp.Text + "\r\n£" + Fields[9] });
                                            //temp.Text = temp.Text + "\r\n£" + Fields[9]; 
                                        }
                                    }
                                    if (temp.Text != compare_txt)//check if value has changed, if yes blink
                                    { temp.BackColor = Color.LightGreen; }
                                    else
                                    { temp.BackColor = Color.Lavender; }
                                    break;
                                case 2:
                                    compare_txt = temp.Text;
                                    this.Invoke(new AddText1(AddText), new object[] { ctrl_name, "" });
                                    //temp.Text = "";
                                    if (Fields.Length >= 5)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[4]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, Fields[4] });
                                            //temp.Text = Fields[4];
                                        }
                                    }
                                    if (Fields.Length >= 6)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[5]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, temp.Text + "\r\n£" + Fields[5] });
                                            //temp.Text = temp.Text + "\r\n£" + Fields[5];
                                        }
                                    }
                                    if (temp.Text == compare_txt)
                                    { temp.BackColor = Color.Thistle; }
                                    else
                                    { temp.BackColor = Color.LightGreen; }
                                    break;
                                case 3:
                                    compare_txt = temp.Text;
                                    this.Invoke(new AddText1(AddText), new object[] { ctrl_name, "" });
                                    //temp.Text = "";
                                    if (Fields.Length >= 1)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[0]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, Fields[0] });                                            
                                            //temp.Text = Fields[0];
                                        }
                                    }
                                    if (Fields.Length >= 2)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[1]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, temp.Text + "\r\n£" + Fields[1] });                                                                                        
                                            //temp.Text = temp.Text + "\r\n£" + Fields[1];
                                        }
                                    }
                                    if (temp.Text == compare_txt)
                                    { temp.BackColor = Color.FromArgb(192, 192, 255); }
                                    else
                                    { temp.BackColor = Color.LightGreen; }
                                    break;
                            }
                        }
                        else if (j == 2)
                        {
                            switch (k)
                            {
                                case 4:
                                    compare_txt = temp.Text;
                                    this.Invoke(new AddText1(AddText), new object[] { ctrl_name, "" });
                                    //temp.Text = "";
                                    if (Fields.Length >= 1)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[0]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, Fields[0] });
                                            //temp.Text = Fields[0]; 
                                        }
                                    }
                                    if (Fields.Length >= 2)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[1]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, temp.Text + "\r\n£" + Fields[1] });                                                                                                                                    
                                            //temp.Text = temp.Text + "\r\n£" + Fields[1];
                                        }
                                    }
                                    if (temp.Text == compare_txt)
                                    { temp.BackColor = Color.FromArgb(255, 192, 192); }
                                    else
                                    { temp.BackColor = Color.LightGreen; }
                                    break;
                                case 5:
                                    compare_txt = temp.Text;
                                    this.Invoke(new AddText1(AddText), new object[] { ctrl_name, "" });
                                    //temp.Text = "";
                                    if (Fields.Length >= 5)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[4]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, Fields[4] });
                                            //temp.Text = Fields[4]; 
                                        }
                                    }
                                    if (Fields.Length >= 6)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[5]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, temp.Text + "\r\n£" + Fields[5] });                                                                                                                                    
                                            //temp.Text = temp.Text + "\r\n£" + Fields[5]; 
                                        }
                                    }
                                    if (temp.Text == compare_txt)
                                    { temp.BackColor = Color.MistyRose; }
                                    else
                                    { temp.BackColor = Color.LightGreen; }
                                    break;
                                case 6:
                                    compare_txt = temp.Text;
                                    this.Invoke(new AddText1(AddText), new object[] { ctrl_name, "" });
                                    //temp.Text = "";
                                    if (Fields.Length >= 9)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[8]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, Fields[8] });
                                            //temp.Text = Fields[8];
                                        }
                                    }
                                    if (Fields.Length >= 10)
                                    {
                                        if (!string.IsNullOrEmpty(Fields[9]))
                                        {
                                            this.Invoke(new AddText1(AddText), new object[] { ctrl_name, temp.Text + "\r\n£" + Fields[9] });
                                            //temp.Text = temp.Text + "\r\n£" + Fields[9];
                                        }
                                    }
                                    if (temp.Text == compare_txt)
                                    { temp.BackColor = Color.Lavender; }
                                    else
                                    { temp.BackColor = Color.LightGreen; }
                                    break;
                            }
                        }
                    }
                }
            }
        }

        public delegate void AddText1(string ctrl_n, string text_a);
        private void AddText(string ctrl_name, string text_assign)
        {
            TextBox temp = null;// = (TextBox)findCtrl(ctrl_name);
            foreach (Control ctl in this.Controls)
            {
                if ((ctl is TextBox) && (ctl.Name == ctrl_name))
                { temp = (TextBox)ctl; }
            }
            temp.Text = text_assign;
        }

        private void makeMyRows(int count)
        {
            int X = 10, Y = 23;
            for (int i = 1; i <= count; i++)
            {
                Label label = new Label();
                label.Name = "lbl" + i.ToString();
                label.Location = new Point(X, Y);
                label.BackColor = Color.Transparent;
                label.Font=new Font("Calibri Sans-Serif", 10);
                label.Font = new Font(label.Font, FontStyle.Bold);
                label.ForeColor = Color.White;
                this.Controls.Add(label);
                X = X + 118;
                for (int j = 1; j <= 6; j++)
                {
                    TextBox tb = new TextBox();
                    tb.Name = "txt" + i.ToString() + j.ToString();
                    tb.ReadOnly = true;
                    tb.Location = new Point(X,Y);
                    tb.Size = new Size(55, 30);
                    tb.Font = new System.Drawing.Font("Arial, Helvetica, sans-serif", (float)7.5);
                    tb.TextAlign = HorizontalAlignment.Center;
                    tb.BorderStyle = BorderStyle.FixedSingle;
                    tb.Font = new Font(tb.Font, FontStyle.Regular);
                    tb.Multiline = true;
                    switch (j)
                    { 
                        case 1:
                            tb.BackColor = Color.Lavender;
                            break;
                        case 2:
                            tb.BackColor = Color.Thistle;
                            break;
                        case 3:
                            tb.BackColor = Color.FromArgb(192, 192, 255);
                            break;
                        case 4:
                            tb.BackColor = Color.FromArgb(255, 192, 192);
                            break;
                        case 5:
                            tb.BackColor = Color.MistyRose;
                            break;
                        case 6:
                            tb.BackColor = Color.Lavender;
                            break;

                    }
                    this.Controls.Add(tb);
                    X = X + 61;
                }
                X = 10; Y = Y + 36;
            }
        }

        //************preventing flicker*************
        int originalExStyle = -1;
        bool enableFormLevelDoubleBuffering = true;

        protected override CreateParams CreateParams
        {
            get
            {
                if (originalExStyle == -1)
                    originalExStyle = base.CreateParams.ExStyle;

                CreateParams cp = base.CreateParams;
                if (enableFormLevelDoubleBuffering)
                    cp.ExStyle |= 0x02000000;   // WS_EX_COMPOSITED
                else
                    cp.ExStyle = originalExStyle;

                return cp;
            }
        }

        private void TurnOffFormLevelDoubleBuffering()
        {
            enableFormLevelDoubleBuffering = false;
            this.MaximizeBox = true;
        }

        private void Rates_Shown(object sender, EventArgs e)
        {
            TurnOffFormLevelDoubleBuffering();
        }

        //******************************************

        private void pictureBox2_Click(object sender, EventArgs e)
        {

        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            this.Refresh();
            RefreshRates(marketId1);
        }

        private void pictureBox1_MouseLeave(object sender, EventArgs e)
        {
            pictureBox1.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.Refresh1));
        }

        private void pictureBox1_MouseEnter(object sender, EventArgs e)
        {
            pictureBox1.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.Refresh_hover));
        }

        private void Rates_FormClosing(object sender, FormClosingEventArgs e)
        {
            t.Abort();
            Webservicethread.Abort();
        }

    }
}
Brad Werth
  • 17,411
  • 10
  • 63
  • 88
Samy S.Rathore
  • 1,825
  • 3
  • 26
  • 43
  • 5
    Instead of multiple forms, can't you put the logic in a DLL to call the web service and call DLL Asynchronously? – Ram Aug 27 '12 at 09:40
  • Got some questions reg. this. Where exactly do you have posted pieces of code? I mean, could you point out where do you start Webservicethread? And what fillData(..) does? And when exactly does the app freeze, when you push start Websericethread or when callback is called? thanks. – alex.b Aug 27 '12 at 09:41
  • @aleksey.berezan shall i put my whole code here?? i'll make edits – Samy S.Rathore Aug 27 '12 at 09:54
  • @Ram hey..can u elaborate ur aproach some more, i am kind of new to this thing :/ – Samy S.Rathore Aug 27 '12 at 10:27
  • Your program could be slowing down from too many `Invoke()` calls. How often are those Textboxes updated? And is that necessary? – H H Aug 27 '12 at 11:20
  • @HenkHolterman the textboxes are updated in every 200 miliseconds, and yes it is kind of important because the values are live and changing at the same pace, please help m really stuck here.. – Samy S.Rathore Aug 27 '12 at 11:27
  • should i use begininvoke() instead?? – Samy S.Rathore Aug 27 '12 at 11:28
  • And think about: no user can really track 1 Textbox changing 5/sec, let alone many Textboxes. – H H Aug 27 '12 at 11:47
  • @HenkHolterman well, i am doing it successfully, just that the processing is too heavy and causes the UI to lag, that is why i have to multithread it....:/ – Samy S.Rathore Aug 27 '12 at 12:07
  • 1. Something tells me that `fillData` method is a bottleneck. Try to measure it's time of work and call us back with result. – alex.b Aug 27 '12 at 12:52
  • 2. Something tells me that you're tring to build from textboxes something looking very-very similary to data grid. What about using grid instead? – alex.b Aug 27 '12 at 12:54
  • @aleksey.berezan yups, u are totally right, i profiled my code with ANTS and filldata is consuming the most % :/ – Samy S.Rathore Aug 27 '12 at 13:11
  • using a grid is just not convenient coz of some requirement that wouls arise at a later stage of the project...:/ – Samy S.Rathore Aug 27 '12 at 13:15

2 Answers2

0

This might help you

  1. Create a background thread which will call the web service asynchronously.

  2. Define a delegate which contains the result web service returns to you.

  3. When you receive the result, using delegate/event pass the result to the form.

  4. On the form display values received from event (use InvokeRequired)

Ram
  • 11,404
  • 15
  • 62
  • 93
  • hey, thanxx for replying, i want to update that as aleksy suggested, the filldata() method that processes the results is being the bottleneck, any suggestios regarding that..:/ – Samy S.Rathore Aug 27 '12 at 13:13
0

Well, given fillData is bottleneck, you gonna' do a lot of optimization. And it's a bit hard for me to tell what exactly should be changed in code in order to make it fast enough.

The only thing I could suggest now is to optimize that part:

   foreach (Control ctl in this.Controls)
                        {
                            if ((ctl is TextBox) && (ctl.Name == ctrl_name))
                            { temp = (TextBox)ctl; }
                        }

1. Try to use this.Controls.Find()
2. Try to cache control instead of searching it. 3. Have fun :)

alex.b
  • 4,547
  • 1
  • 31
  • 52
  • hey aleksey, thanxx for the dir'n, i'll just implement that in my code, but this feels more like a Trade-Off condition b/w perforance and multiple-instances of the same form ...:( – Samy S.Rathore Aug 28 '12 at 06:23