Reconnect to server in 5 seconds c# (Task) [duplicate] - c#

Hi I am trying to find a method of waiting a number of milliseconds before moving to the next line of code,
I have looked into Thread.Sleep but this will freeze the main form, I would like this to remain active.
I tried timers and stopwatches and both freeze the main form when they should be posting to a console when they tick.
I couldn't find a way of using task.delay or background worker in the wait I wanted either.
Pseudo Code:
Wait 2 - 6 seconds
Log "waiting"
Log "waiting"
Log "waiting"
Stop Waiting - Run next line of code.
The methods I have tried just freeze up the form and fill the log afterwards, I just want a simple method of waiting without freezing the form and without having to deal with events being called which would mean the next line isn't run.
Any help would be awesome because I am still new to c# and its been driving me a bit mad :(

The await keyword, in conjunction with Task.Delay makes this trivial.
public async Task Foo()
{
await Task.Delay(2000);
txtConsole.AppendText("Waiting...");
DoStuff();
}

Try using a DispatcherTimer. It's a pretty handy object that does all the work of delegating to the UI thread.
For example:
private DispatcherTimer _dtTimer = null;
public Constructor1(){
_dtTimer = new DispatcherTimer();
_dtTimer.Tick += new System.EventHandler(HandleTick);
_dtTimer.Interval = new TimeSpan(0, 0, 0, 2); //Timespan of 2 seconds
_dtTimer.Start();
}
private void HandleTick(object sender, System.EventArgs e) {
_uiTextBlock.Text = "Timer ticked!";
}

Timer should work fine in this case, unless you put Thread.Sleep in its handler or the handler itself takes too much time to complete.
You haven't specified the UI framework that you use or .Net version, but for the latest .Net you can use async/await. That way, UI would not be frozen while your code awaits for the background task
void async MyMethod()
{
var result = await Task.Run(() => long_running_code);
}

DateTime Tthen = DateTime.Now;
do
{
Application.DoEvents();
} while (Tthen.AddSeconds(5) > DateTime.Now);

Related

Blocking main thread with SemaphoreSlim until background event arrives

Yes, I know, there are tons of threads on this topic. I read a lot of them and used them often (more or less) successfully. Now I got an old DLL (programmed in .net 4.0) and that is using BackgroundWorkers to fire result events. Whatever I try to stop and wait for such a result seems to miss its mark. But maybe some of you have ideas that I haven't tried yet.
I register the answer event in thread 1 (according to Thread.CurrentThread.ManagedThreadId), call the method to connect and wait with a SemaphoreSlim for the answer. But in each and every constellation I get the answering event AFTER the timeout occurred. The event is on thread 3 and when I tried to raise the AwaitAsync() (also with Await) of the SemaphoreSlim on a special Thread.Run(() => ...); it was on thread id 8. But still thread number 3 always just comes AFTER the timeout.
private void ConnectDevice()
{
MobileDevice.DeviceConnected += new DeviceConnectedHandler(MobileDevice_Connected);
...
mSignal = new SemaphoreSlim(0, 1);
MobileDevice.Connect();
// Task.Run(() => MobileDevice.Connect());
int i = Thread.CurrentThread.ManagedThreadId;
var task = Task.Run(() => mSignal.WaitAsync(new TimeSpan(0, 0, cTimeout)).GetAwaiter().GetResult());
// Task<bool> task = Task.Run(async () => await WaitForSemaphore());
// var result = task.Wait();
IsConnected = task.Result;
// WaitForSemaphore();
...
}
private async Task<bool> WaitForSemaphore()
{
int j = Thread.CurrentThread.ManagedThreadId;
if (!await mSignal.WaitAsync(new TimeSpan(0, 0, 5)))
{
throw new MobileDeviceException("Device timed out");
}
return true;
}
//private void WaitForSemaphore()
//{
// if (!mSignal.Wait(new TimeSpan(0, 0, cTimeout)))
// {
// throw new MobileDeviceException("Device timed out");
// }
//}
private void MobileDevice_Connected(object sender, DeviceConnectedEventArgs e)
{
int k = Thread.CurrentThread.ManagedThreadId;
mSignal?.Release();
...
}
And yes, I know this is chaotic. But I wanted to show you, that I tried a lot already. I tried a lot more, but deleted also a mass of mistakes.
I begin to think, that, even if the answer comes on thread id 3, the listener to these events is still the main thread (id 1). And as long as that is blocked, the event doesn't gets fired.
Am I right? And how do I get around this? Register the event on a different way?
Oh, I nearly forgot: I am serving an Interface here and this will become a plugin for a complex application, so I cannot make the Connect-Method async and use the async/await-Pattern. I have to call the Connect of the device, block the main thread till the answer arrives and then release it, so the main part of the application can continue.
Anyone an idea of solving this?
Edit (the 1st): Ok, to sort some confusions out. This is a plugin that is called from a non-async method. I cannot change the calling method to an async one or else I would have to reprogram a few hundred thousand lines of code.
The call comes from the main program and looks like this:
firstDevice.Connect();
I COULD change that to something within reason, but I cannot use something like: await firstDevice.Connect(); or else I would have to change the main programs calls all to async. And this is simply out of question.
The connect method inside the plug-in I could change. At this moment it does nothing more than to call the ConnectDevice(), so I could test some things with async, SemaphoreSlims, and so on.
And as soon as I use an await inside an async method, the calling thread moves on. There would also have to be an await, but you cannot use await outside of async methods.
What seems strange to me is, that Thread.CurrentThread.ManagedThreadId says that both threads are thread 1. But when I step through they are clearly moving asynchronously.
Edit (the 2nd): I heard a clue. Maybe the problem here is the BackgroundWorker of the API. A colleague of mine once heard that the BackgroundWorker blocks the GUI-thread, when it is started on the GUI-thread. So the events of the API cannot get to me on thread 3 until the GUI-thread is released. So the solution would be to call the MobileDevice.Connect(); on a different thread. But it seems that the API will have to change. So we will discuss this internally. As soon as I have a solution I will update this a last time for anyone interested.
Edit (the 3rd): Ok, it seems nearly all of this solutions are working my problem was really with this goddamn BackgroundWorker. The API communicated with the mobile device on thread 1. And as soon as you block thread 1, there is also a block in the communication between API and device, so the answer of the API never comes...
But thanks anyway for you help. ;)
You may wrap the Connect call in a TaskCompletionSource:
public static class DeviceExtension
{
public static Task ConnectAsync(this Device device)
{
var tcs = new TaskCompletionSource<object>();
device.DeviceConnected += (s, e) => tcs.SetResult(null);
device.Connect();
return tcs.Task;
}
}
which you would call like
await MobileDevice.ConnectAsync();
or in a synchronous context like
MobileDevice.ConnectAsync().Wait();

foreach async sleep method

I am trying to make my foreach loop asynchronous. The loop loops the first time, does something then it will wait 40 seconds and then the loop loops again does something, waits 40 seconds etc...
In my situation I am looping around tweets, getting the tweet user name and then sending a tweet to them.
I tried using the Thread.Sleep(40000) method but that just freezes the app and I can't use it, and the loop doesn't stop for 40 seconds and then loops again. The app freezes but the loop doesn't, the tweets are getting sent without even waiting at all. This how my code looks like
private void tweetButton_Click(object sender, EventArgs e)
{
var tweets= .........
foreach (var tweet in tweets)
{
// Do Something
System.Threading.Thread.Sleep(40000);
}
How would I let the foreach loop to pause before looping again on its self, and how would I make it pause without freezing my application?
https://msdn.microsoft.com/en-us/library/hh194873(v=vs.110).aspx
I think you can await Task.Delay(40000); - to me that would be an 'async sleep' like you've asked for.
Alternatively, you could kick off a timer. The timer is probably a better choice, but will run on a threadpool thread.
EDIT: Not sure why this got -1...but if anyone has an explanation, I'd be interested.
I've verified that 'await Task.Delay(xyz)' does work for this purpose. Naturally, you'd need the async keyword to be added.
static async void DoSomething()
{
for(var i = 0;i<25;i++)
{
// Do Something
await Task.Delay(1000);
Console.WriteLine("Sending a Tweet");
}
}
I can't speak to the performance, but it seems to work fine for me.
You want your code to run on a different thread, so it doens note impede the code running in your winforms gui thread.
The best way for you specific needs is a timer that you kickoff once and that then does your job.
{
Timer t = new Timer();
t.Interval = 50000;
t.Elapsed += T_Elapsed;
t.Start();
}
private static void T_Elapsed(object sender, ElapsedEventArgs e)
{
}
If you need to access your winforms controls from here, you can use invoke, so the commands are placed into the the gui threads message loop.
control.Invoke((MethodInvoker)(() =>
{
//Do your thing
}));
You could implement background process in form. That would works in your case.

Alternative for Thread.Sleep() to temporarily suspend program

See the code at the bottom of this post. It's supposed to add "3" to the listbox, then "2" a second later, then "1" a second later and then run the main code of the program. However, once I execute the program it just stays blank 3 seconds long, after which all 3, 2, and 1 are shown, after which all the code directly starts. I want to visually see every number show up with a one second delay. How do I do this?
private void Main()
{
countdown();
//Main Code
}
private void countdown()
{
listBox1.Items.Clear();
listBox1.Items.Add("3");
System.Threading.Thread.Sleep(1000);
listBox1.Items.Add("2");
System.Threading.Thread.Sleep(1000);
listBox1.Items.Add("1");
System.Threading.Thread.Sleep(1000);
listBox1.Items.Clear();
}
async / await to the rescue:
private async void OnButtonClick(object sender, EventArgs e)
{
listBox1.Items.Clear();
listBox1.Items.Add("3");
await Task.Delay(1000);
listBox1.Items.Add("2");
await Task.Delay(1000);
listBox1.Items.Add("1");
await Task.Delay(1000);
listBox1.Items.Clear();
}
First: Why isn't anything happening?
The reason is, that you are currently in the UI thread. By doing Thread.Sleep you suspend the very same thread you expect to draw the items you just added.
Second: How to work around this?
As #CodeCaster mentioned, you could use a Timer to do all this. You could also put your code in a Thread and call the Add method by using a Dispatcher or the SynchronizationContext class and it's Send method.
Third: A small hint on the Sleep method.
Usually it should do what you expect it to, but there is no guarantee for that. Calling Sleep means that your thread will be suspended for roughly the amount of time you want it to. See this answer
You can use a Timer having the interval set to 1000. Start the timer when you want it to raise Tick event. Stop it to stop raising Tick event. Handle the Tick event and run the code in intervals.
But to have a countdown 3-2-1 function using async-await as it's suggested in the other answer is good idea:
private async void countdown()
{
listBox1.Items.Clear();
listBox1.Items.Add("3");
await Task.Delay(1000);
listBox1.Items.Add("2");
await Task.Delay(1000);
listBox1.Items.Add("1");
await Task.Delay(1000);
listBox1.Items.Clear();
}
Put a listBox1.Refresh(); after every Sleep() call.
You are letting the thread sleep, but the UI does not get repainted automagically.

How can I wait for a timer to finished before I execute next line of code without putting the thread to sleep?

I am trying to have a timed execution of some code in my application. I am creating multiple threads in my application, and I am trying to get them to execute code at the same time.
I am wondering if there is a way to make my thread wait until my timer has finished before it continues on with the next bit of code without putting it to sleep? Currently I am doing just that but surely there is another way. Can anyone offer some assistance?
System.Timers.Timer _timer = new System.Timers.Timer();
_timer.Interval = (2000);
_timer.Elapsed += (sender, e) =>
{
//code to execute
_timer.Enabled = false;
};
_timer.Enabled = true;
Thread.Sleep(2000);
//code to invoke my finished delegate
You can use Task.Delay for a cleaner asynchronous approach:
Task.Run(async delegate
{
await Task.Delay(2000);
//do stuff here
});
Task creates asynchronous operations and (mostly) abstracts away the threading model. When you're inside a routine marked async, the await keyword means "wait for this to finish and then run". In the example above, this is all happening outside your executing thread.
You don't even need to use a Timer, just use async/await feature, that will not block your UI Thread
private async void SomeMethod()
{
await Task.Delay(2000); // wait two seconds asynchronously
// your code goes here
// this code will be executed after two seconds
}
I am trying to have a timed execution of some code in my application. I am creating multiple threads in my application, and I am trying to get them to execute code at the same time.
One way to do it (based on your multiple threads comment) is to use the CountDownEvent class.
using (var mySignal = new CountDownEvent(doWorks.Count))
{
foreach (var doWork in doWorks)
{
// Start Threads example
Task.Factory.StartNew(() =>
{
// do work
// signal this thread done
mySignal.Signal();
}
}
// wait for all threads
mySignal.Wait();
// All threads are done.
}
Assuming you absolutely must do it this way, you could use EventWaitHandle
As mentioned, you're likely better off using another implementation such as those mentioned.

How to use signalling mechanism for performing intensive work (that do not overlap) with a thread and manualresetevent in C#?

I have an existing application with 1 thread running some intensive work in the background every numOfMinutesInterval. This was previously done using Thread.Sleep (sleeping for the entire interval period) but I've read that Thread.Sleep is evil and it's sloppy design, so I wanna change to a signalling mechanism. Below is the code I just wrote (using dispatcher timer from wpf, but I think in this small scenario it's the same for winforms timer as well).
The dispatcher (running in the UI thread) ticks every second, and inside the tick function it checks whether interval has passed, and if so, it will signal the manualresetevent Set(). I'm wondering if this is bad design if the intensive work extends pass the interval period? If I set the numOfMinutesInterval = 1, but the work took 1 minute and 1 second, does that mean we'll skip 1 set() call, since the tick is attempting to set() the event while work is still being done and the worker thread is not yet blocking.
Please notice also that I've set lastWorkDoneTime = DateTime.Now; after calling Set(), should I move it to the worker thread instead (calling lastWorkDoneTime = DateTime.Now; just before manualResetEvent.WaitOne();)?
If this is bad design, what should I do to change it? Thanks for reading!
//thread work done here
private void MyDoWork_ThreadStart()
{
while(FlagApplicationStillRunning == true)
{
//do the intensive work here
manualResetEvent.WaitOne();
}
}
// tick every second
private int numOfMinutesInterval = 1;
private DateTime lastWorkDoneTime = DateTime.Now;
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if((DateTime.Now - lastWorkDoneTime).Minutes > numOfMinutesInterval)
{
manualResetEvent.Set();
lastWorkDoneTime = DateTime.Now;
}
}
You could just start a task and have that perform the intensive work.
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if ((DateTime.Now - lastWorkDoneTime).Minutes > numOfMinutesInterval)
{
Task.Factory.StartNew(DoIntensiveWork());
lastWorkDoneTime = DateTime.Now;
}
}
As far as setting the lastWorkDoneTime that is up to you. If you set it in what fires off the task, you have the possibility of two or more tasks running at the same time performing the work. If you set it at the end of the function performing the work you introduce a delay that is based on how long it takes to complete the work.
I would actually look into using one of the timer objects and let that handle the timing for you instead of using the DispatcherTimer_Tick event. There is System.Timers.Timer, System.Threading.Timers, and others.
To help determine what timer option would work best for you:
Comparing the Timer Classes in the .NET Framework Class Library

Categories

Resources