-2

I have a C# console application in which I am looping through list of users and creating each making an entry into another database.

If the user creation has failed for a UserId then I need to try again for the same user for a maximum of 5 times, between each try I need to wait for 10 seconds..

For this wait purpose I am using System.Threading.Thread.Sleep

foreach(var user in Users)
{
   counter = 0;
   CreateUserDetails(user.UserId);
   if(!userCreatedSuccesfully)
   {
     do
       {
           counter++;
           System.Threading.Thread.Sleep(10000);
           CreateUserDetails(user.UserId);
       }
     while(userCreatedSuccesfully == false && counter <5)
   }
}

I would like to replace Thread.Sleep with WaitHandle. How do I leverage WaitHandle in my scenario here? Please suggest if there is any other better approach instead of WaitHandle.

Note : I have posted only partial code here with only what is required.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • I personally prefer `Task.Delay()` with an `async` pattern – Stefano Cavion Jun 28 '21 at 11:09
  • 1
    "I would like to replace thread.sleep with waithandle" - why? what are you trying to achieve? this isn't meant to be rude - it matters; for example, `await Task.Delay(...)` might be a better approach – Marc Gravell Jun 28 '21 at 11:21
  • @MarcGravell I tried replacing Thread.Sleep(10000) with await Task.Delay(10000) and the moment the breakpoint reaches the line await Task.Delay(10000) the application stops running and exits with no exception, the control is not going to catch block also – Passionate Jun 28 '21 at 11:29
  • @MarcGravell The reason i am trying to remove thread.sleep is because i heard that its not good to use it as during the wait period thread.sleep blocks the thread. – Passionate Jun 28 '21 at 11:30
  • 1
    @Passionate that sounds to me like you have a console application that isn't awaiting the thing you're doing; if that is the case: you can make your `Main` method `async Task Main()` (etc) and make sure you `await` the thing. – Marc Gravell Jun 28 '21 at 11:36
  • @MarcGravell I tried changing my main method is Program.cs to static async Task Main(string[] args) and when i build my application i am getting an exception 'Program does not contain a static main method suitable for an entry point'... i am using c# 7.0 – Passionate Jun 28 '21 at 11:53
  • @Passionate that might be a 7.1 feature, from memory; is updating language version an option? – Marc Gravell Jun 28 '21 at 11:56
  • @MarcGravell I upgraded to 7.1 and the error is gone , in my main method i have a line which says 'Return 0' and i am facing an error here 'Since 'Program.Main(string[]) is an async method that returns Task , a return keyword must not be followed by an object expression. Did you intend to return 'Task'? – Passionate Jun 28 '21 at 12:11
  • 1
    So your program behaves exactly as you would like it to behave, but you want to remove the `Thread.Sleep` because you've heard that it's not good to use it? My suggestion is to just go with the `Thread.Sleep`, and forget about it. If it's not broken, don't fix it. – Theodor Zoulias Jun 28 '21 at 12:26
  • @Passionate if changing from an `int Main` method, use `async Task Main` – Marc Gravell Jun 28 '21 at 12:44
  • 1
    So, one thread blocks. Who cares? Just ignore the mumbling from the peanut gallery and leave it as it is, as suggested by @TheodorZoulias:) – Martin James Jun 28 '21 at 13:19

2 Answers2

0

If your aim here is simply to avoid explicit thread blocking, then await Task.Delay(timeout); is a good alternative. This, however, requires you to change the calling code to async and ensure everything is awaited. If you have a static void Main() method, you can change that to static async Task Main(); likewise, for static int Main() you can change that to static async Task<int> Main() - noting that async Main() requires C# 7.1 or above.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • The `async Task Main` syntax is just syntactic sugar for a [blocking call](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.1/async-main) to `MainAsync().GetAwaiter().GetResult();`. So the OP's goal, which is to avoid blocking a thread while their single-threaded program is doing nothing, cannot be achieved with an asynchronous entry point. The only way to achieve their goal is to create a zero-threaded process, which is not possible on the Windows OS (or on any other OS most likely). – Theodor Zoulias Jun 28 '21 at 12:58
  • @TheodorZoulias while that is true, that is an implementation detail; in my experience, this is *often* (not always) code that is used in multiple ways - essentially library code that is, in one instance, used from a console. In that view, enabling fully async usage is more than an empty goal. – Marc Gravell Jun 28 '21 at 13:13
  • Marc the question is: is async usage more than an empty goal in this specific application? My assumption is that the OP's question is production oriented, and they didn't just post a toy application with the goal of learning asynchronous programming. – Theodor Zoulias Jun 28 '21 at 13:22
-2

I think in this case you need to use lock operator, becouse the lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.

lock (x)
{
    // Your code...
}

When your CreateUserDetails(user.UserId); command finishes next your thread can get access, etc.

Mansur Kurtov
  • 726
  • 1
  • 4
  • 12
  • 1
    Locks would only help with concurrency, since they are re-entrant; it isn't clear that concurrency is the happening here; also - taking a lock isn't sufficient as a test here - you'd pretty much need to use a Wait+Pulse here, to ensure that the main thread doesn't acquire it too early; in short: I don't think this answer really addresses the fundamental question – Marc Gravell Jun 28 '21 at 12:44