0

I am not sure if this is the proper place to ask, but this site has always been a trememdous help for me in other areas.

I have a perfect candidate for background threading in a small, personal Winforms application I am writing, and I am seeking help in trying to implement it properly/correctly.

This is the call from the presentation layer:

    private void btnGetSeasonSchedule_Click(object sender, EventArgs e){
        Cursor.Current = Cursors.WaitCursor;
        objSchedule.RetreiveSeasonSchedule();
        MessageBox.Show("Finished");
        Cursor.Current = Cursors.Default;
    }

This is the code in the BLL:

    public class SeasonSchedule{
        public ForumAssistantDAL.SeasonSchedule objSchedule = new ForumAssistantDAL.SeasonSchedule();

        public void RetreiveSeasonSchedule(){
            DataTable dtData = GetGamesInRange(DateTime.Parse("2015-10-07"), DateTime.Parse("2016-04-30"));

            // this call is to an SQLBulkUpdate function in the DAL
            objSchedule.UploadSchedule(dtData);
        }

        // ***** BackgroundWorker Candidate #1 *****
        // my first thought is to have the entire function below as a backgroundworker process
        //as it is used in a few other locations in the application *****

        private DataTable GetGamesInRange(DateTime startDate, DateTime endDate){
            DataTable dtScheduleTable = objSchedule.CreateScheduleTable();

            // ***** BackgroundWorker Candidate #1 *****
            // instead of the entire function, just put this ForEach loop in a BackgroundWorker

            foreach (DateTime day in EachDay(DateTime.Parse(startDate.ToString("yyyy-MM-dd")), DateTime.Parse(endDate.ToString("yyyy-MM-dd")))){
                //build proper URL using URIBuilder
                //...URL requires a formatted date, hence the necessity of re-building it in a foreach loop
                var uriBuilder = new UriBuilder();
                uriBuilder.Scheme = "http";
                uriBuilder.Host = "my.datasource.address";
                uriBuilder.Path = "path_part_1/path_part_2/" + day.ToString("yyyy-MM-dd") + ".jsonp";
                var uri = uriBuilder.Uri;

                try{
                    string json = new WebClient().DownloadString(uri);

                    json = json.Replace("loadScoreboard(", "");
                    json = json.Replace(")", "");

                    GameCollection gameDay = objSchedule.ParseGames(json);

                    // ***** BackgroundWorker Candidate #2 *****
                    // each GameCollection can contain from zero to N games
                    // each game is added to a temporary DataTable
                    // when the ForEach loop is complete, the entire DataTable is returned, and the DataTable is SQLBulkCopy-ied to the database server

                    foreach (DeserializedGame game in gameDay.Games){
                        objSchedule.InsertGame(game, dtScheduleTable, day);
                    }
                }
                catch (WebException ex){
                    if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null){
                        var resp = (HttpWebResponse)ex.Response;
                        if (resp.StatusCode == HttpStatusCode.NotFound){
                            // HTTP 404 - the page was not found, continue with next in the for loop
                            continue;
                        }
                    }
                    //throw any other exception - this should not occur
                    throw;
                }
            }

            return dtScheduleTable;
        }

        private IEnumerable<DateTime> EachDay(DateTime from, DateTime thru){
            for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
                yield return day;
        }
    }

My goal is the following:

  • multi-thread this application correctly
  • once the multi-threading is in place, I to implement two ProgressBars:
    • one for the ForEach loop (to track the processing for each day)
    • one for each DeserializedGame in the ForEach loop (BackgroundWorker Candidate #2)

I have looked at ThreadStart and ParameterizedThreadStart (which I believe is the proper one to use), but I feel I get very lost, very quickly when it comes to implementing the threading properly and correctly. Threading is a new concept for me, so any "for dummies" help you can offer would be greatly appreciated.

Kulstad
  • 79
  • 8
  • what is your exact issue? or, are you simply looking for a code-review? if that's the case, check out https://codereview.stackexchange.com/ – d.moncada Jan 10 '16 at 18:21
  • 1
    This is actually not a great case for multi-threading - rather, it's a great case for asynchronous I/O. Have a look at `await`, and the asynchronous methods (e.g. `HttpClient.GetAsync`). – Luaan Jan 10 '16 at 18:22
  • @d.moncada thank you for the link. I will definitely utilize it. – Kulstad Jan 10 '16 at 18:25
  • @Luaan What is the difference between asynchronous I/O and offloading the work to a different thread? – Kulstad Jan 10 '16 at 18:26
  • 4
    @Kulstad Read this great (as usual) [answer](http://stackoverflow.com/questions/34680985/what-is-the-difference-between-asynchronous-programming-and-multithreading/34681101#34681101) by Eric Lippert – Ivan Stoev Jan 10 '16 at 18:32
  • @IvanStoev Thank you for that article, it definitely clears things up a lot. The entirety of my application depends on what data is loaded from the code I posted, so I don't want the user of the application to be able to do anything else until this process is completed, however I do want the user to know that the application is still working (hence the desire for ProgressBars). Without trying to change my initial question, is Asynch still the best option instead of threading? – Kulstad Jan 10 '16 at 18:49
  • Yeah, it's really just about "Do A while exposing yourself to a few complications" and "Do A while wasting a thread and exposing yourself to a whole lot of extra complications". You should only be thinking about adding multi-threading when you have a significant amount of CPU work to do. The main advantage of `await` (which can be used with both async I/O and threading) is that you can pretty much write code that is synchronous (i.e. step-by-step) without actually blocking. And you're not accessing the UI from multiple threads, which is always a good thing :) – Luaan Jan 11 '16 at 08:18

0 Answers0