Wait for a while without blocking main thread
Thread.Sleep(500)
will force the current thread to wait 500ms. It works, but it's not what you want if your entire application is running on one thread.
In that case, you'll want to use a Timer
, like so:
using System.Timers;
void Main()
{
Timer t = new Timer();
t.Interval = 500; // In milliseconds
t.AutoReset = false; // Stops it from repeating
t.Elapsed += new ElapsedEventHandler(TimerElapsed);
t.Start();
}
void TimerElapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Hello, world!");
}
You can set AutoReset
to true (or not set it at all) if you want the timer to repeat itself.
Waiting for a result before continuing and without blocking UI
This is basically what you want. I'm violating a couple best-practices here, but just showing it's not that complicated. One thing to keep in mind is that the user can now click this button multiple times in a row. You might consider disabling it before processing. Or you can do a Monitor.TryEnter()
to make sure it's not already running.
private async void buttonProcess_Click(object sender, RoutedEventArgs e)
{
textBlockStatus.Text = "Processing...";
bool processed = await Task.Run(() => SlowRunningTask());
}
private bool SlowRunningTask()
{
Thread.Sleep(5000);
return true;
}
Synchronous Wait Without Blocking the UI-Thread
You can use a DispatcherTimer
for that sort of thing.
Edit: This might do as well...
private void Wait(double seconds)
{
var frame = new DispatcherFrame();
new Thread((ThreadStart)(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(seconds));
frame.Continue = false;
})).Start();
Dispatcher.PushFrame(frame);
}
(Dispatcher.PushFrame
documentation.)
Starting with .NET 4.5 you can use async
event handlers and Task.Delay
to get the same behaviour. To simply let the UI update during such a handler return Dispatcher.Yield
.
Android sleep() without blocking UI
You can use postDelayed()
method like this:
handler=new Handler();
Runnable r=new Runnable() {
public void run() {
//what ever you do here will be done after 3 seconds delay.
}
};
handler.postDelayed(r, 3000);
Adding Delay In A For Loop Without Blocking UI
Would this solution work? Instead of using dispatch_after, I use dispatch_async with a [NSThread sleepForTimeInterval] block, which allows me to put a delay anywhere that I need in my custom queue.
dispatch_queue_t myCustomQueue;
myCustomQueue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(myCustomQueue, ^ {
NSLog(@“Task1”);
});
dispatch_async(myCustomQueue, ^ {
[NSThread sleepForTimeInterval:2.5];
});
dispatch_async(myCustomQueue, ^ {
NSLog(@“Task2”);
});
dispatch_async(myCustomQueue, ^ {
[NSThread sleepForTimeInterval:3.0];
});
dispatch_async(myCustomQueue, ^ {
NSLog(@“Task3”);
});
dispatch_async(myCustomQueue, ^ {
[NSThread sleepForTimeInterval:2.0];
});
How to wait for thread to complete without blocking UI
I'm very surprised you haven't worked with any of these before but I would really recommend reading about threading in C# since it's fundamentally important to understand the intricacies and learning the language.
Below are three different ways you can achieve what you want:
1. Using reset events (further reading: https://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim(v=vs.110).aspx). If your C# version doesn't have the ManualResetEventSlim
, replace it with ManualResetEvent
and change Wait()
with WaitOne()
class LockingWithResetEvents
{
private readonly ManualResetEvent _resetEvent = new ManualResetEvent(false);
public void Test()
{
MethodUsingResetEvents();
}
private void MethodUsingResetEvents()
{
ThreadPool.QueueUserWorkItem(_ => DoSomethingLong());
ThreadPool.QueueUserWorkItem(_ => ShowMessageBox());
}
private void DoSomethingLong()
{
Console.WriteLine("Doing somthing.");
Thread.Sleep(1000);
_resetEvent.Set();
}
private void ShowMessageBox()
{
_resetEvent.WaitOne();
Console.WriteLine("Hello world.");
}
}
2) Using Task Parallel Library (TPL). Further reading: https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
class LockingWithTPL
{
public void Test()
{
Task.Factory.StartNew(DoSomethingLong).ContinueWith(result => ShowMessageBox());
}
private void DoSomethingLong()
{
Console.WriteLine("Doing somthing.");
Thread.Sleep(1000);
}
private void ShowMessageBox()
{
Console.WriteLine("Hello world.");
}
}
3) Using Async/Await. Further reading: https://msdn.microsoft.com/en-us/library/hh191443.aspx
class LockingWithAwait
{
public void Test()
{
DoSomething();
}
private async void DoSomething()
{
await Task.Run(() => DoSomethingLong());
ShowMessageBox();
}
private async void DoSomethingLong()
{
Console.WriteLine("Doing somthing.");
Thread.Sleep(10000);
}
private void ShowMessageBox()
{
Console.WriteLine("Hello world.");
}
}
Also good to know: Mutex (https://msdn.microsoft.com/en-us/library/system.threading.mutex(v=vs.110).aspx), Semaphore (https://msdn.microsoft.com/en-us/library/system.threading.semaphore(v=vs.110).aspx), Lock (https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx), SemaphoreSlim (https://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim(v=vs.110).aspx), Monitor (https://msdn.microsoft.com/en-us/library/system.threading.monitor(v=vs.110).aspx) and Interlocked (https://msdn.microsoft.com/en-us/library/system.threading.interlocked(v=vs.110).aspx).
C# Need to wait for thread to finish without blocking UI thread
await Task.Run(() => resetEvent.WaitOne());
should do the trick. ManualResetEvent
is not awaitable and can't use await keyword directly on it, so you need to wrap it in task
Run a task for two seconds without blocking UI
Yes, I've tried too, but if I do the Task.Delay with async tasc the problem is that normal and reverse mode are tried at the same time. Finally I've made it doing this:
Private Sub autocheck_btStart_Click(sender As Object, e As EventArgs) Handles autocheck_btStart.Click
If Not currentlyTesting Then
currentlyTesting = True
principal.setRecording(True, ecu)
Dim t As Task = Task.Run(Sub()
startTesting()
End Sub)
principal.setRecording(False, ecu)
currentlyTesting = False
End If
End Sub
Public Sub startTesting()
For Each test In tests
tbDebug.AppendText("Testing motor " + test.getName() + Environment.NewLine)
test.executeTest()
Next
showResults()
End Sub
Public Sub executeTest()
isTesting = True
ckNormal.Checked = True
Thread.Sleep(2000)
ckNormal.Checked = False
Thread.Sleep(200)
ckReverse.Checked = True
Thread.Sleep(2000)
ckReverse.Checked = False
Thread.Sleep(200)
isTesting = False
End Sub
Thanks for your advices!!
Related Topics
How to Make a Background Worker Thread Set to Single Thread Apartment
What Does System.Double[*] Mean
Why Is Try {...} Finally {...} Good; Try {...} Catch{} Bad
Creating PDF Files at Runtime in C#
How to Add a String to a String[] Array? There's No .Add Function
Query String Not Working While Using Attribute Routing
Should I Use Appdomain.Currentdomain.Basedirectory or System.Environment.Currentdirectory
Send Http Post Message in ASP.NET Core Using Httpclient Postasjsonasync
Set Cultureinfo in ASP.NET Core to Have a . as Currencydecimalseparator Instead of ,
Event to Detect System Wake Up from Sleep in C#
Minimizing All Open Windows in C#
Forms Not Responding to Keydown Events
How to Make JSON.Net Serializer to Call Tostring() When Serializing a Particular Type
Does Entity Framework 4 Code First Have Support for Identity Generators Like Nhibernate
Why Does Visual Studio Type a Newly Minted Array as Nullable