So I have a simple test using Monitor.Wait with a timeout set for three seconds. It's my understanding that, when the time expires, a virtual pulse is sent to the monitor to release the wait. In my test, however, that never seems to happen. Can someone explain what's going on. Here's my test code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace BlockingMethodFoo
{
class Program
{
static void Main(string[] args)
{
WaitFoo foo = new WaitFoo();
foo.StartMethod();
Console.WriteLine("Done. Press enter");
Console.ReadLine();
}
}
public class WaitFoo
{
private object _waitObj = new object();
private string _message = string.Empty;
public void StartMethod()
{
Thread waitThread = new Thread(new ThreadStart(new Action(() => { WaitMethod(); })));
_message = string.Empty;
Console.WriteLine("Starting wait");
_message = "Time Out";
lock (_waitObj)
{
waitThread.Start();
Monitor.Wait(_waitObj, TimeSpan.FromSeconds(3));
}
Console.WriteLine(_message);
}
private void WaitMethod()
{
lock (_waitObj)
{
_message = Console.ReadLine();
Monitor.Pulse(_waitObj);
}
}
}
}
Monitor.Wait will return false if the timeout expires and it couldn't get the lock.
http://msdn.microsoft.com/en-us/library/tdc87f8y.aspx
You have to check the return of Monitor.Wait and for example throw a TimeOutException if you see fit.
Related
I need the simplest possible Timer to repeat my code infinitely every 5 seconds. No external classes or whatnot.
Just:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Now the following code will be repeated over and over");
//////////////// FOLLOWING CODE /////////////////
/* the repeated code */
//////////////// END OF FOLLOWING CODE /////////////////
}
}
How can I do that?
Use while(true) with Thread.Sleep
using System.Threading;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Now the following code will be repeated over and over");
while(true)
{
//////////////// FOLLOWING CODE /////////////////
/* the repeated code */
//////////////// END OF FOLLOWING CODE /////////////////
Thread.Sleep(5000);
}
}
}
Simplest form of it :
using System.Threading;
static void Main(string[] args)
{
bool breakConditionFlag = false;
ManualResetEvent waitHandler = new ManualResetEvent(false);
while(breakConditionFlag)
{
//Your Code
waitHandler.WaitOne(TimeSpan.FromMilliseconds(1000)); // 1000 is the Arbitary value you can change it to Suit your purpose;
}
}
Why ManualResetEvent ?
The event makes more efficient use of the processors- you're not having to wake the parent thread up to poll. The kernel will wake you up when the event fires.
Use Timer.
static void Main(string[] args)
{
Timer timer = new System.Threading.Timer((e) =>
{
Console.WriteLine("Now the following code will be repeated over and over");
}, null, 0, (int)TimeSpan.FromSeconds(5).TotalMilliseconds);
Console.Read();
}
Here I have called Console.WriteLine multiple times, you can write your code block instead of it.
You can use Thread.Sleep(5000); But again its also external class according to the OP.
But I would suggest a better solution using Async and Await. One more thing you should have a termination condition, so that you dont produce an infinite call to avoid unnecessary memory consumption.
public static async Task RepeatActionEveryInterval(Action action, TimeSpan interval, CancellationToken cancelToken)
{
while (true)
{
action();
Task task = Task.Delay(interval, cancelToken);
try
{
await task;
}
catch (TaskCanceledException)
{
return;
}
}
}
static void Main(string[] args)
{
CancellationTokenSource cancelToken = new CancellationTokenSource(TimeSpan.FromSeconds(50));
Console.WriteLine("Start");
RepeatActionEveryInterval(() => Console.WriteLine("Repeating Code"), TimeSpan.FromSeconds(5), cancelToken.Token).Wait();
Console.WriteLine("End");
Console.Read();
}
In this example this code will write till 50 seconds.
Use this code for call your function recursively for every 5 seconds.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace recurssiveWithThread
{
class Program
{
static void Main(string[] args)
{
RecWork();
}
public static int i = 0;
public static void RecWork()
{
// Do the things whatever you needed here
i++;
Console.WriteLine(i);
//Thread to make the process to sleep for sometimes
Thread.Sleep(5000);
//Call your function here
RecWork();
}
}
}
Use BackgroundWorker class:
Reference links:
Background worker
If you are using framework >= 4.5.2 QueueBackgroundWorkItem
QueueBackgroundWorkItem
I'm trying to get a simple label value to change from another thread, and already tried 3 different threading mechanisms (Tasks, Thread, Background worker) and am now at a loss why the control won't update.
I have a method in an unrelated class like this:
public static void SetOverlayText(string text, bool fade = false)
{
Thread myThread = new Thread(FadeOverlayText);
OverlayForm.SetLabelText(text);
if (fade)
{
myThread.Start();
}
}
and
private static void FadeOverlayText()
{
OverlayForm.ClearLabelText();
}
My form is a regular windows form and has that method:
public void ClearLabelText()
{
this.Invoke((MethodInvoker)delegate
{
StatusText.Text = "Something should happen"
StatusText.Refresh();
});
}
The method appears to be getting called, but nothing happens.
You should not need Refresh.
This should work:
public void ClearLabelText()
{
if (StatusText.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
StatusText.Text = "Something should happen";
});
}
else
{
StatusText.Text = "Something should happen";
}
}
Are you shure, you use the correct control and at no other point the string is changed, so that it seems not to work? Please check every thing.
Also be sure, that you only call ClearLabelText once in your second thread, becuase after ClearLabelText is finished, the thread is not alive anymore.
This will update your text every second, as long as the application runs:
private static void FadeOverlayText()
{
var uiThread = <<Your UI Thread>>;
while(uiThread.IsAlive)
{
OverlayForm.ClearLabelText();
Thread.Sleep(1000);
}
}
EDIT:
here is a simple example i've made and it works. Additionaly to your StatusText label, I've added button1, which change the text too.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest2
{
public partial class Form1 : Form
{
Thread mainThread = null;
public Form1()
{
InitializeComponent();
mainThread = Thread.CurrentThread;
Thread myThread = new Thread(FadeOverlayText);
myThread.Start();
}
private void FadeOverlayText()
{
while (mainThread.IsAlive)
{
ClearLabelText();
Thread.Sleep(1000);
}
}
public void ClearLabelText()
{
if (StatusText.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
StatusText.Text = "Something should happen";
});
}
else
{
StatusText.Text = "Something should happen";
}
}
private void button1_Click(object sender, EventArgs e)
{
StatusText.Text = "It works!";
}
}
}
One way to make this work is to use a timer that does
StatusText.Text= yourstring;
Every n milliseconds, and make your thread update the 'yourstring' variable to whatever you want.
Kindly help me. My idea is to continually print Numeric values form 0 to 1000 using thread concept. In case unexceptionally my application closes, how can I write the code WAITING for currently running thread tasks to complete.
Here by i mention sample code...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using System.IO;
namespace Test_AsyncFactorCaller
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public bool Work()
{
int nSleep = 100;
WriteMessage(string.Format("Going to Thread Sleep State for {0} sec", nSleep));
for (int i = 0; i < nSleep; i++)
{
WriteMessage(string.Format("Sleeping = {0}", i));
Thread.Sleep(1000);
}
WriteMessage("Going to Thread Wakeup State");
return true;
}
public void Work_Done(IAsyncResult result)
{
WriteMessage("Work_Done");
AsyncFactorCaller t = (AsyncFactorCaller)((AsyncResult)result).AsyncDelegate;
bool bResult = t.EndInvoke(result);
WriteMessage(string.Format("Result {0}",bResult));
result.AsyncWaitHandle.Close();
}
public void WriteMessage(string sMessage)
{
using (StreamWriter sw = new StreamWriter(#"C:\ThreadLog.txt", true))
{
sw.WriteLine(sMessage);
sw.Close();
}
}
private void btn_asyncCaller_Click(object sender, EventArgs e)
{
try
{
AsyncFactorCaller dGate_caller = new AsyncFactorCaller(Work);
AsyncCallback Completed_callBack = new AsyncCallback(Work_Done);
AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(null);
IAsyncResult result = dGate_caller.BeginInvoke(Completed_callBack, "Test thread");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
public delegate bool AsyncFactorCaller();
}
}
If you are really sure that this is what you need to do, try using a WaitHandle.
AutoResetEvent _blocker = new AutoResetEvent(false);
//In background thread
_blocker.Set();
//Where you want to wait for it
_blocker.WaitOne();
Here's my code:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
namespace TestAsync
{
class Program
{
private const string conn = "Data Source=UNREACHABLESERVER;Initial Catalog=master;Integrated Security=True";
static void Main(string[] args)
{
try
{
TestConnection();
}
catch
{
Console.WriteLine("Caught in main");
}
}
private static async void TestConnection()
{
bool connected = false;
using (var tokenSource = new CancellationTokenSource())
using (var connection = new SqlConnection(conn))
{
tokenSource.CancelAfter(2000);
try
{
await connection.OpenAsync(tokenSource.Token);
connected = true;
}
catch(TaskCanceledException)
{
Console.WriteLine("Caught timeout");
}
catch
{
Console.Write("Caught in function");
}
if (connected)
{
Console.WriteLine("Connected!");
}
else
{
Console.WriteLine("Failed to connect...");
throw(new Exception("hi"));
}
}
}
}
}
The output is:
Caught timeout
Failed to connect...
But then my program terminates with an unhandled exception. Instead, I'm wanting my program to have the thrown exception handled in the main thread and print out Caught in main. How can I make that work?
EDIT
Here's my updated code that works the way I want:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
namespace TestAsync
{
class Program
{
private const string conn = "Data Source=UNREACHABLESERVER;Initial Catalog=MyFiles;Integrated Security=True";
static void Main(string[] args)
{
try
{
TestConnection().Wait();
}
catch
{
Console.WriteLine("Caught in main");
}
Console.ReadLine();
}
private static async Task TestConnection()
{
using (var tokenSource = new CancellationTokenSource())
using (var connection = new SqlConnection(conn))
{
tokenSource.CancelAfter(2000);
await connection.OpenAsync(tokenSource.Token);
}
}
}
}
This is not possible. Your call to TestConnection() will return (and thus execution on the main thread will continue) once your first await is encountered. Your catch blocks and throwing the exception will execute on another thread and go unobserved by the main thread.
This one just one reason why async void should be avoided. If you need to write an async void function, it must be completely self-contained (including error handling logic). You would be much better off writing an async Task function. The simplest approach would be to modify your call in the Main method to this:
TestConnection().Wait()
This will, of course, cause the main thread to block while executing the function (you'll also have to change the signature to async Task before this will compile).
i know i can get the Thread Name by calling Thread.CurrentThread.Name
but i got a tricky scenario.
i created two thread, each launch a new object (says objA) and run a method.
inside the object (objA) method (objAM), i create another object (says objB) and run a method (objBM).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TESTA a = new TESTA();
}
}
class TESTA
{
private Thread t;
public TESTA()
{
t = new Thread(StartThread);
t.Name = "ABC";
t.IsBackground = true;
t.Start();
t = new Thread(StartThread);
t.Name = "XYZ";
t.IsBackground = true;
t.Start();
}
private void StartThread()
{
objA thisA = new objA();
}
}
class objA
{
private System.Threading.Timer t1;
public objA()
{
objAM();
t1 = new Timer(new TimerCallback(testthread), null, 0, 1000);
}
private void objAM()
{
Console.WriteLine("ObjA:" + Thread.CurrentThread.Name);
}
private void testthread(object obj)
{
objB thisB = new objB();
}
}
class objB
{
public objB()
{
objBM();
}
private void objBM()
{
Console.WriteLine("ObjB:" + Thread.CurrentThread.Name);
}
}
}
but the value of Thread.CurrentThread.Name in objB return empty.
How can i get the Thread Name inside objBM?
From description of System.Threading.Timer: The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.
Thus your testthread method executed on unnamed ThreadPool thread. Btw you can verify it by calling Thread.CurrentThread.IsThreadPoolThread.