How to implement data exchange between the main loop and threads? Suppose there is such a pseudocode Example:

namespace First { public class Test { public static string Outout1 = string.Empty; private static System.Threading.Thread SThread; public static string Func1() { pass; } public static void GetTimeNow() { for(;;){ Outout1 += Func1(); System.Threading.Thread.Sleep(4000); } } public static string GetTimeNow2() { pass; } private static void RunThread() { if (SThread == null || SThread.ThreadState != System.Threading.ThreadState.Running) { SThread = new System.Threading.Thread(GetTimeNow); SThread.Start(); } } public static void MainFunc() { for(;;){ Outout1 += GetTimeNow2(); RunThread() ; System.Threading.Thread.Sleep(5000); } } } } 

The main function MainFunc is MainFunc into an infinite loop in this loop and we call the function GetTimeNow2 . Which returns us data to the variable Outout1 . Next, it runs the RunThread function RunThread which runs the GetTimeNow function in a separate thread.

The GetTimeNow function GetTimeNow infinite loop, and it calls Func1 , which writes data to Outout1 .

The question is whether the correct data will always be in the variable Outout1 , namely whether the data from GetTimeNow2 and GetTimeNow will be visible and if you reset it at the end of the loop, it will also be reset in GetTimeNow which is running in a separate thread? Example:

  for(;;){ Outout1 += GetTimeNow2(); RunThread(); System.Threading.Thread.Sleep(5000); Outout1 = ""; } 

Please tell me how to implement this method correctly, so that you can work with the Outout1 variable both in the main loop and in the loop that is running in a separate thread? and how to do it if you start not 1 stream but 2-5 Example:

  for(;;){ Outout1 += GetTimeNow2(); RunThread(); RunThread1(); RunThread2(); System.Threading.Thread.Sleep(5000); Outout1 = ""; } 
  • one
    If possible, avoid sharing variables between threads. Tell us more about the meaning of your task. - VladD
  • I want to unload the main loop, because some tasks are not processed in time due to the fact that there is a return of the data in the loop in the other function. Therefore, I decided to put all laborious operations into separate streams, but with the ability to return the data after processing to the Outout1 variable and work with this variable in the main loop - Alexey Manuilov
  • one
    And let's get out even higher. Forget about the variable. You have a calculation. What data do you want to receive in the calculation process? Why do you need, for example, intermediate data, and not the result? - VladD
  • There is a processing of counters that change with great speed. There are such situations when one function in a cycle starts processing one counter, from the other counter it skips the event due to the fact that the main thread takes processing of the first counter. That's why I want to render processing 4 counters into separate threads so as not to interfere with the main loop. Based on the intermediate data, I make changes to the variable. If conditions fall under the filter in the intermediate data, I make changes to Outout1. - Alexey Manuilov

1 answer 1

As one of the options - you can use asynchronous programming using the keywords async and await. You will get the same result without the need to create threads and without risk to get a race condition due to a shared variable. Here is the pseudocode:

 public class MyTestClass { public static string outputString = String.Empty; public static string GetFirstString() { return "world"; } public static string GetSecondString() { return "!!!"; } public static async Task FirstTimer() { for(int i = 0; i < 10; i++) { outputString += GetFirstString(); await Task.Delay(50); } } public static async Task SecondTimer() { for (int i = 0; i < 10; i++) { outputString += GetSecondString(); await Task.Delay(50); } } public static string GetStartString() { return "Hello "; } public static async Task MyMain() { for (int i = 0; i < 1 ; i++) { outputString += GetStartString(); await FirstTimer(); await SecondTimer(); await Task.Delay(500); Console.WriteLine(outputString); outputString = String.Empty; } } 

You can check it or in UnitTest. For example:

  [TestMethod] public async Task TestAsyncLoop() { await MyTestClass.MyMain(); } 

Or in the console application

 public static async Task Main() { await MyTestClass.MyMain(); } 

Note 1: in the console application, apply async to the Main function appeared only from the C # 7.1 compiler version. In other versions of the compiler, you need to use

 public static void Main () { MyTestClass.MyMain().Wait(); } 

Note 2: in applications with a graphical interface, you need to use asynchronous methods, taking into account the execution context, so as not to fall into a deadlock state.

  • 2
    Uh ... Well, async / await is good, but writing to a shared variable without locking is bad. Async / await is so good that you can return a value from Task 'and not think about synchronization. - VladD
  • The question of working with a shared variable from multiple threads. How does your answer correlate with this? You have neither infinite cycles, no parallelism, no answer to the question posed - tym32167
  • With async / await, of course, it's good, but I would just like to return data from the stream to a variable, I’m interested in the process of such manipulation for experience. the topic of flows is not simple, and therefore turned to experts here - Alexey Manuilov