0

I've asked a question on how to know when a string of another other party library code changes in my code. I can get access to the string itself at any time. but can't implement INotifyPropertyChanged since it's not my code.

I was offered to use a BackgroundWorker and this solution does work for me! but, I was trying to make sure it is the best solution and got an advise to look at TPL, further researching showed that Task.Run of TPL might be a better solution, as mentioned here for example: Task parallel library replacement for BackgroundWorker? but I couldn't implement it in code.

I am trying to replace this code by Task.Run (Thanks to @a.azemia)

        BackgroundWorker bw = new BackgroundWorker();
    bw.DoWork += (s, e) =>
        {
            while (true)
            {
                if (!fc.SecondString.Equals(AnotherPartyLibrary.firstString))
                {
                    fc.SecondString = AnotherPartyLibrary.firstString;
                }
                Thread.Sleep(1000);
            }
        };
    bw.RunWorkerAsync();

I couldn't find any example that fit my scenario and tried to learn from other examples with no success. I need a while loop inside the task and it needs to run asynchronously like the BackgroundWorker does. couldn't find any example with a while loop in the task, so I am not sure of how this can be done.

I've also read that Lambda expressions uses more resources and it was shown in some test that I've seen so I would've liked to avoid Lambda if possible.

Thanks for the help!

Community
  • 1
  • 1
Ray
  • 407
  • 1
  • 3
  • 15
  • As for the down votes, what's wrong with my question? I would just want to mention I've spent many hours(!!) trying to get it work. I am not asking to save my time but because I've really tried everything I could and I am really stuck. – Ray Jan 26 '15 at 22:47
  • For your simple scenario, I see no benefit in changing. It could have been done with just a Timer... – Idle_Mind Jan 26 '15 at 22:57
  • 1
    Avoiding lamda expression because of some resource overhead is a micro performance improvement. Ignore it and just use lamdas – Sievajet Jan 26 '15 at 23:04
  • 1
    For future reference, I have a [blog post series on replacing `BackgroundWorker` with `Task.Run`](http://blog.stephencleary.com/2013/05/taskrun-vs-backgroundworker-intro.html). But in this case, I don't think BGW **or** `Task.Run` is appropriate; I recommend you use Ned's answer. – Stephen Cleary Jan 26 '15 at 23:42
  • Thanks everyone, for clearing these things out for me. @StephenCleary, I've been all over your blog already trying to figure out how this works, thanks for your advice. :) – Ray Jan 27 '15 at 01:40
  • @StephenCleary, Any thoughts/insights on using async/await with a "task" that never ends (it's an infinite loop)? Is there a downside to awaiting something that never ends from the Load() event of a Form, for instance? – Idle_Mind Jan 27 '15 at 16:32
  • @Idle_Mind: There's a bit of memory overhead. It's fine to do this a limited number of times (i.e., on startup), but you want to avoid a situation where you await forever an unlimited number of times (i.e., from a button click). – Stephen Cleary Jan 27 '15 at 16:36

2 Answers2

2

Try this (untested):

public async Task DoWork()
{
   while (true)
  {
      if (!fc.SecondString.Equals(AnotherPartyLibrary.firstString))
      {
         fc.SecondString = AnotherPartyLibrary.firstString;
      }

       await Task.Delay(1000);
  }    
}     

I've used Task.Delay instead of Thread.Sleep as the former does not block a thread while delay is happening. You can invoke this function with await

 await DoWork();
NeddySpaghetti
  • 13,187
  • 5
  • 32
  • 61
  • Thanks for your answer @Ned Stoyanov, I couldn't get it to build, if I put the await DoWork(); code on the Form_Load method, VS error says: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'. I am probably doing something wrong am I.. Thanks again. – Ray Jan 27 '15 at 01:41
  • The method that you are calling it from needs to be `async` and ideally return a `Task` or a `Task`. This tends to have a chain reaction effect in your code and you may need to mark multiple methods as `async` – NeddySpaghetti Jan 27 '15 at 01:56
  • Thanks @Ned Stoyanov, sorry for all my questions, I am new to all of this parallel programing.. so what if I want to call this DoWork method from the Form_Load method? could/should I make it async? – Ray Jan 27 '15 at 02:15
  • Yes, you should make it `async`. You'd declare it like this `private async void Form1_Load(object sender, EventArgs e)` – NeddySpaghetti Jan 27 '15 at 03:08
0

I still see no real benefit, but here you go:

    private Task T;

    private void Form1_Load(object sender, EventArgs e)
    {

        // ... make sure your string stuff is setup first ...

        T = Task.Run(delegate() { 
            while (true)
            {
                // ... code ...
                System.Threading.Thread.Sleep(1000);
            }
        });
    }    
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • Thanks for your answer, your code does work for me, this string updates a few times a second sometimes so I just wanted to be sure I am doing the best possible thing. – Ray Jan 27 '15 at 00:45