question

MarkusFreitag-0088 avatar image
0 Votes"
MarkusFreitag-0088 asked JackJJun-MSFT commented

C# Timer WinForms

Hello,

  public System.Threading.Timer AsyncProgramChangeTimer = null;
         public void MyStartTimer()
         {
             lock (this)
             {
                 AsyncProgramChangeTimer = new System.Threading.Timer((o) =>
                 {
                     if (ProgramChangeDone == false)
                     {
                         //do whatever
                         Trace.WriteLine("Timer was coming!!!");
                         Action<string> DelegateTeste_ModifyText = THREAD_MOD;
                         Invoke(DelegateTeste_ModifyText, $"Timer was coming!!! {DateTime.Now}");
                         AsyncProgramChangeTimer.Change(2000, Timeout.Infinite);
                     }
                     else
                     {
                         Trace.WriteLine("Timer no repeat!!!");
                     }
                 }, null, 0, Timeout.Infinite);
             }
         }


  private void THREAD_MOD(string test)
         {
             txtStatus.Text += Environment.NewLine + test;
         }
    

   private void btnStopTimer_Click(object sender, EventArgs e)
         {
             ProgramChangeDone = !ProgramChangeDone;
             MyStartTimer();
         }

My goal.

A) Action or Func
How do I have to write it if I want a return value?

How do I have to write it if I want to have one return value and two passing parameters?

How do I have to write it if I want to have no return value and three passing parameters?

B) Lock
Do I need the lock so no one can access it?

C) Via a button I would like to switch the timer monitoring on or off.

D) Invoke or Dispatcher ?
Update the controls, which mechanism is correct?
Is this correct in my example?









dotnet-csharpwindows-forms
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

JackJJun-MSFT avatar image
0 Votes"
JackJJun-MSFT answered JackJJun-MSFT commented

@MarkusFreitag-0088, Welcome to Microsoft Q&A,

A:
Action delegate doesn't return the value and Func delegate can return one result.

Example:

(no parameter and return one value)

  Func<string> delegatechangetest = Changetext;
  string result = delegatechangetest();
    
   private string Changetext()
         {
             string result = Environment.NewLine+sometext;
             return result;  
         }

(Two parameters and return one value)

  Func<string, string, string> delegatechangetest = Changetext;
   string result = delegatechangetest($"Timer was coming!!! {DateTime.Now}", "yes");
    
  private string Changetext(string test1, string test2)
         {
             string result = Environment.NewLine + test1 + test2;
             return result;  
         }

B:
Yes, you could use lock to stop any other thread to acquire the lock until the lock is released.

C:
Please try the following code to use a button to stop or start the timer:


 private void button1_Click(object sender, EventArgs e)
         {
             ProgramChangeDone = !ProgramChangeDone;
             if(AsyncProgramChangeTimer==null)
             {
                 MyStartTimer();
             }
             else
             {
                 AsyncProgramChangeTimer.Change(Timeout.Infinite, Timeout.Infinite);
                 AsyncProgramChangeTimer = null;
             }
                    
         }

D:
You could use Invoke or Dispatcher both to update the control:

Invoke:

  Func<string, string, string> delegatechangetest = Changetext;
  string result = delegatechangetest($"Timer was coming!!! {DateTime.Now}", "yes");
  txtStatus.Invoke((MethodInvoker)delegate { txtStatus.Text += result; });

Dispatcher:


 Func<string, string, string> delegatechangetest = Changetext;
  string result = delegatechangetest($"Timer was coming!!! {DateTime.Now}", "yes");
   Dispatcher dispUI = Dispatcher.CurrentDispatcher;
   DispatcherOperation dispatcherOperation = dispUI.BeginInvoke(DispatcherPriority.Normal, (MethodInvoker)delegate { txtStatus.Text += result; });

I think your code example is enough to get what you want except the button to start or stop the timer.
Full completed code example:( Use Function delegate:)


 public System.Threading.Timer AsyncProgramChangeTimer = null;
 public void MyStartTimer()
 {
     lock (this)
     {
         AsyncProgramChangeTimer = new System.Threading.Timer((o) =>
         {
         if (ProgramChangeDone == false)
         {
             //do whatever
             Console.WriteLine("Timer was coming!!!");
             //Action<string, string> DelegateTeste_ModifyText = THREAD_MOD;
             //Invoke(DelegateTeste_ModifyText, $"Timer was coming!!! {DateTime.Now}", "yes");
             Func<string, string, string> delegatechangetest = Changetext;
             string result = delegatechangetest($"Timer was coming!!! {DateTime.Now}", "yes");
             txtStatus.Invoke((MethodInvoker)delegate { txtStatus.Text += result; });
                 //Dispatcher dispUI = Dispatcher.CurrentDispatcher;
                 //DispatcherOperation dispatcherOperation = dispUI.BeginInvoke(DispatcherPriority.Normal, (MethodInvoker)delegate { txtStatus.Text += result; });->Use dispatcher to update control
             AsyncProgramChangeTimer.Change(2000, Timeout.Infinite);



             }
             else
             {
                 Console.WriteLine("Timer no repeat!!!");
             }
         }, null, 0, Timeout.Infinite);
     }
 }
 public bool ProgramChangeDone = true;

 private string Changetext(string test1, string test2)
 {
     string result = Environment.NewLine + test1 + test2;
     return result;  
 }
 private void THREAD_MOD(string test1,string test2)
 {
     txtStatus.Text += Environment.NewLine + test1+test2;
 }

 private void button1_Click(object sender, EventArgs e)
 {
     ProgramChangeDone = !ProgramChangeDone;
     if(AsyncProgramChangeTimer==null)
     {
         MyStartTimer();
     }
     else
     {
         AsyncProgramChangeTimer.Change(Timeout.Infinite, Timeout.Infinite);
         AsyncProgramChangeTimer = null;
     }
            
 }


Best Regards,
Jack


If the answer is the right solution, please click "Accept Answer" and upvote it.If you have extra questions about this answer, please click "Comment".

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.








· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Looks good.
One question, sorry is not clear for me.

 private void button1_Click(object sender, EventArgs e)
  {
      ProgramChangeDone = !ProgramChangeDone;
      if(AsyncProgramChangeTimer==null)
      {
          MyStartTimer();
      }
      else
      {
          AsyncProgramChangeTimer.Change(Timeout.Infinite, Timeout.Infinite);
          AsyncProgramChangeTimer = null;
      }
                
  }

I would like to have an interval of 2000ms. Why infinite?

   AsyncProgramChangeTimer.Change(Timeout.Infinite, Timeout.Infinite);


Thanks.


0 Votes 0 ·
JackJJun-MSFT avatar image JackJJun-MSFT MarkusFreitag-0088 ·

@MarkusFreitag-0088, thanks for the feedback. based on my test and research, the code AsyncProgramChangeTimer.Change(Timeout.Infinite, Timeout.Infinite); means that it will stop your timer. It will not affect the 2000ms of interval.
According to the Microsoft doc Timeout.Infinite Field, when we set Timeout.Infinite, the value is used to suspend the thread indefinitely.



1 Vote 1 ·