简体   繁体   中英

C# winforms and threads

I have win form with one button "start" and when i click on it start reading .txt file row by row and post requests to a server. My question is - How can i make when i click on "start" to read 50 rows from file then stop and wait for another click on "start". Is threading the only possible solution here? This is my button:

private void btnStart_Click(object sender, EventArgs e)
    {
        List<string> List = LoadFromFile("FILE");
        int dialogid = 0;
        foreach (string g in List)
        {
            dialogid++;
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("number", g);
            parameters.Add("dialogid", dialogid.ToString());

            if (InvokeService(this.tbWebServiceURL.Text, parameters) == false)
            {
                MessageBox.Show("ERROR!", "ERROR");
                return;
            }
        }

And here is my post request:

private bool InvokeService(string ServiceURL, Dictionary<string, string> parameters)
    {          
        try
        {           
            string data = "";
            int cnt = 0;

            byte[] dataStream = Encoding.UTF8.GetBytes(data);
            WebRequest webRequest = WebRequest.Create("URL");
            webRequest.Method = "POST";
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.ContentLength = dataStream.Length;

            foreach (KeyValuePair<string, string> kvk in parameters)
            {
                webRequest.Headers.Add(kvk.Key, kvk.Value);
            }

            WebResponse response = webRequest.GetResponse();
            Stream dataStreamResponse = response.GetResponseStream();
            StreamReader reader = new StreamReader(dataStreamResponse);
            string responseFromServer = reader.ReadToEnd();
            Console.WriteLine(responseFromServer);
            reader.Close();
            dataStreamResponse.Close();
            response.Close();

Most important here is not read whole file with one click on "start". Must wait for another "start". Read 50 rows and wait to click on 'start" to read second 50 rows. Hope now is more clear.

BackgroundWorker outline - not tested:

        private void button1_Click(object sender, EventArgs e)
        {
            if (fileReader == null) fileReader = new StreamReader("File");
            string thisLine;
            netJob bwClass = new netJob(this.tbWebServiceURL.Text);
            for (int i = 0; i < 50; i++)
            {
                thisLine = fileReader.ReadLine();
                if(thisLine=="")break;
                dialogid++;
                Dictionary<string, string> newDict = new Dictionary<string, string>();
                newDict.Add("number", thisLine);
                newDict.Add("dialogid", dialogid.ToString());
                bwClass.Fparams.Add(newDict);
            }
            backgroundWorker1.RunWorkerAsync(bwClass);
        }



    class netJob
    {
        private string FURL;
        public List< Dictionary<string, string> > Fparams;
        private Dictionary<string, string> FthisParam;
        public string errorMess;
        public string responseFromServer;
        public List<string> responsesFromServer;
        public netJob(String URL)
        {
            FURL = URL;
            Fparams= new List< Dictionary<string, string> >();
            responsesFromServer=new List<string>();
            errorMess = "";
        }
        public void run()
        {
            foreach (Dictionary<string, string> thisDict in Fparams)
            {
                InvokeService(FURL, thisDict);
                if (errorMess == "") responsesFromServer.Add(responseFromServer);
                else
                {
                    responsesFromServer.Add(errorMess);
                }

            }
        }

        private bool InvokeService(string ServiceURL, Dictionary<string, string> parameters)
        {
            try
            {
                string data = "";
                byte[] dataStream = Encoding.UTF8.GetBytes(data);
                WebRequest webRequest = WebRequest.Create("URL");
                webRequest.Method = "POST";
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.ContentLength = dataStream.Length;

                foreach (KeyValuePair<string, string> kvk in parameters)
                {
                    webRequest.Headers.Add(kvk.Key, kvk.Value);
                }

                WebResponse response = webRequest.GetResponse();
                Stream dataStreamResponse = response.GetResponseStream();
                StreamReader reader = new StreamReader(dataStreamResponse);
                responseFromServer = reader.ReadToEnd();
                reader.Close();
                dataStreamResponse.Close();
                response.Close();
            }
            catch (Exception e)
            {
                errorMess = e.Message;
            }
        }
    }
}

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            netJob thisJob = e.Argument as netJob;
            thisJob.run();
        }


        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
                netJob thisJob = e.Result as netJob;
                foreach (string thisResponse in thisJob.responsesFromServer)
                {
                    Console.WriteLine(thisResponse);
                }
        }

Not sure you need threads for this. Only one reasone - processing 50 lines is slow operation and you won't freeze UI for this time, then yes - you should delegate this work to a worker thread rather than doing it in UI thread, otherwise you should be fine with simple solution like shown below:

bool isInProgress = false;

private void OnStartButtonClick(object sender, EventArgs args)
{
  // avoid multiple clicks mess
  if (isInProgress) 
  {  
    return;
  }

  try
  {
     startButton.isEnabled = false;
     isInProgress = true;    
     int counter = 50;

     while (counter-- > 0)
     {
        var singleLine = File.ReadLine(path); 
        var message = CreateMessageFromLine(singleLine);
        transport.PostMessageToServer(message);
     }
   }
   finally
   {
       isInProgress = false;
       startButton.isEnabled = true;
   }
}

I would do it like this:

private void StartButton_Click(object sender, EventArgs args)
{
    StartButton.Enabled = false;
    try
    {
        for (int i = 0; i < 50; i++)
        {
            string line = file.ReadLine();
            //Send to server
        }
    }
    finally
    {
        StartButton.Enabled = true;
    }
}

Disable the start button while reading 50 lines, then enable it so you can read another 50 lines.

Reading 50 lines at a time is fast enough so you don't need threads. Use a BackgroudWorker for the Send to server part.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM