C#: Non-blocking sleep - c#

I'm writing a small application for my Logitech G510 LCD keyboard and am experiencing a little problem. After drawing to my screen, I'd like my program to become idle and remain active as process, but without consuming any resources from my computer.
However, I need to open a Form whenever a certain event is raised. I believe Thread.Sleep() is not the best way to do that.
Here is what my code roughly looks like:
int main(){
InitLCD();
DrawStuff();
Wait();
}
void HandleEvent(){
//Create a Form if none exists
}
//Must be called before exiting
void OnExit()
{
CloseLCD();
}
Could maybe a seperate thread which cares for the event be a solution? If so, how?
EDIT:// The application is an invisible WinForm application. This means, no form is created upon start. Only when said event is raised, an actual form is created.

Try Logic This way :
public static class Program
{
private static AutoResetEvent waithandle = new AutoResetEvent(true);
static void Main()
{
LCDClass lcd = new LCDClass();
lcd.mid_event += LcdOnMidEvent;
lcd.exit_event += LcdOnExitEvent;
lcd.init();
Thread thread = new Thread(lcd.DrawStuff);
thread.Start(waithandle);
waithandle.WaitOne();
}
private static void LcdOnExitEvent(object sendet, EventArgs eventArgs)
{
//lcd work finished
}
private static void LcdOnMidEvent(object sendet, EventArgs eventArgs)
{
// handle event, create form
Application.Run(new MyForm());
}
}
internal class LCDClass
{
private AutoResetEvent waithandle;
internal delegate void MyEventHandler(object sendet, EventArgs e);
internal event MyEventHandler mid_event;
protected virtual void OnMidEvent(object sendet)
{
MyEventHandler handler = mid_event;
if (handler != null) handler(sendet, EventArgs.Empty);
}
internal event MyEventHandler exit_event;
protected virtual void OnExitEvent(object sendet)
{
MyEventHandler handler = exit_event;
if (handler != null) handler(sendet, EventArgs.Empty);
}
public void init()
{
}
public void DrawStuff(object state)
{
// do work here
// raise event
mid_event(this, null);
//do more work
// raise event
exit_event(this, null);
waithandle.Set();
}
}

Related

C# callback on new thread

i am having trouble creating a callback on a newly started thread.
I have 2 classes, an API, and the Form.cs. I start a thread running a method in API, from Form.cs, i want to notify a method in Form.cs from inside the method in API.
I am familiar with delegation in Obj-C, but not in C#.
I only included the relevant code.
public partial class Main: Form
{
private Api Connect = new Api();
private void StartStopButton_Click(object sender, EventArgs e)
{
//new thread
Thread ThreadConnect = new Thread(Connect.startAttemptingWithUsername);
ThreadConnect.Start();
}
public void AttemptingWithPasswordMessage(string password)
{
// i want to notify this method from the API
}
}
class Api : UserAgent
{
public void startAttemptingWithUsername()
{
_shouldStop = false;
while (!_shouldStop)
{
Console.WriteLine(username);
// How would i notify AttemptingWithPasswordMessage from here?
System.Threading.Thread.Sleep(1000);
}
}
}
Provide an event to your other class, and fire that event whenever it is relevant based on the processing:
class Api : UserAgent
{
public event Action<string> SomeEvent;//TODO give better name
public void startAttemptingWithUsername()
{
_shouldStop = false;
while (!_shouldStop)
{
Console.WriteLine(username);
var handler = SomeEvent;
if (handler != null)
handler("asdf");
// How would i notify AttemptingWithPasswordMessage from here?
System.Threading.Thread.Sleep(1000);
}
}
}
Then add a handler for that event: (And marshal back to the UI thread)
private void StartStopButton_Click(object sender, EventArgs e)
{
//new thread
Thread ThreadConnect = new Thread(Connect.startAttemptingWithUsername);
ThreadConnect.Start();
Connect.SomeEvent += (data) => Invoke(
new Action(()=>AttemptingWithPasswordMessage(data)));
}

Issue with ballooning threads in periodic processing

I want to do some periodic work on a worker thread which signals when the work is completed. When signaled, I want to wait for 5 seconds and re-do the work. I wrote the following code:
public class WinService : ServiceBase
{
private readonly ManualResetEvent stopPeriodicProcess = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
stopPeriodicProcess.Reset();
ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess, InitializeEngines, null,5000, true);
}
public void InitializeEngines(object state, bool timedOut)
{
engine.LoadSettings();
Task.Factory.StartNew(engine.DoSomeWork); //Fire and forget
}
private void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e)
{
ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess,
(state, timedOut) => DoPeriodicProcess(state, timedOut, e.EngineId), null,
5000, true);
}
public void DoPeriodicProcess(object state, bool timedOut, string engineId)
{
if (timedOut)
{
Task.Factory.StartNew(engine.DoSomeWork); //Fire and forget
}
}
}
public class Engine
{
public event EventHandler<WorkCompletedEventArgs> WorkCompleted;
public void DoSomeWork()
{
//Doing some work..
//Raise an event to signal that the work has been completed
var args = new WorkCompletedEventArgs {EngineId = Settings.EngineId};
RaiseWorkCompletedEvent(args);
}
protected virtual void RaiseWorkCompletedEvent(WorkCompletedEventArgs e)
{
EventHandler<WorkCompletedEventArgs> handler = WorkCompleted;
if (handler != null)
{
handler(this, e);
}
}
}
When I run the code, the CPU usage shows 100% after few seconds. Upon debugging in VS, I see too many alive worker threads waiting at RegisterWaitForSingleObject inside WorkCompletedEventHandler.
Why aren't the threads dying after calling RegisterWaitForSingleObject? Am I missing something?
Not tested but I think this is due to the event not being reset:
private void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e)
{
stopPeriodicProcess.Reset();
ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess,
(state, timedOut) => DoPeriodicProcess(state, timedOut, e.EngineId), null,
5000, true);
}
Moreover I don't understand why you're doing things this way, can't you use a timer, which is precisely designed for this kind of use-case?

How to publish and subscribe to events across different classes

Goal: To change a image on a form when either udp or tcp uses its send method
Problem: I have no idea how to get the event, eventhandler and delegates set up correctly
Send Interface
interface ISendData
{
void Send();
}
Tcp Connection class
//Need some type of delegate??
public class TCPconnection : ISendData
{
void Send()
{
//how invoke/fire a send Event?
}
}
UDP Connection class
//Need some type of delegate??
public class UDPConnection : ISendData
{
void Send()
{
//how invoke/fire a send event?
}
}
the winform which 'should' subscribe to seeing the fired events
public class myForm
{
private DataWatcher datawatcher = new DataWatcher();
private Image statusIndicator = null;
public myform()
{
initComponents();
datawatcher.DataSendActive += new DataWatcherSendHandler(DataSending);
datawatcher.DataSendInactive += new DataWatcherSendHandler(NoDataSending);
}
public void DataSending(object sender, DataWatcherArgs e)
{
statusIndicator = Properties.resources.greenLight;
}
public void NoDataSending(object sender, DataWatcherArgs e)
{
statusIndicator = Properties.resources.redLight;
}
}
The Event/Event handler?? But I really have no Idea what I'm doing here to make this work
public delegate void EventHandler(object sender, EventArgs e);
class DataWatcher
{
public event EventHandler DataSendActive;
public event EventHandler DataSendInactive;
protected virtual void onDataSendActive(System.EventArgs e)
{
if (DataSendActive != null)
{
DataSendActive(this, e);
}
}
protected virtual void onDataSendInactive(System.EventArgs e)
{
if (DataSendInactive != null)
{
DataSendInactive(this, e);
}
}
}
There are many conventions used to do this. Here's my little implementation.
public enum ActivityState
{
Sending,
Receiving,
Idle
}
public interface IDataTransferManager
{
// This event will fire when the activity state changes.
// note that Action<T> is introduced in .NET 3.5
// if you're using .NET 2.0, you can use a delegate.
event Action<ActivityState> DataActivityStateChange;
void Send(byte[] data);
//byte[] Receive();
// ... more methods ... //
}
Now the TcpConnection class will implement this.
public class TcpConnection : IDataTransferManager
{
public event Action<ActivityState> DataActivityStateChange;
public void Send(byte[] data)
{
// we're sending data. fire the change event
FireDataActivityStateChange(ActivityState.Sending);
//TODO: send the data
// we're done sending. Fire the change event
FireDataActivityStateChange(ActivityState.Idle);
}
private void FireDataActivityStateChange(ActivityState state)
{
// helper method, so I don't have to check the event
// to avoid null reference exceptions.
if (DataActivityStateChange != null)
DataActivityStateChange(state);
}
}
Here's the setup for your Form.
class MyForm // :Form
{
IDataTransferManager dataManager;
public MyForm()
{ // here, usually an instance will be passed in,
// so there's only one instance throughout the application.
// let's new up an instance for explanation purposes.
dataManager = new TcpConnection();
dataManager.DataActivityStateChange += (state) =>
{
// NOTE: if you don't like inline,
// you can point this labda to a method.
switch (state)
{
case ActivityState.Sending:
// change the image to the spinning toilet ball
break;
case ActivityState.Receiving:
// change the image to the spinning toilet ball, but reverse :P
break;
case ActivityState.Idle:
// hide it ?
break;
}
};
}
}
Here is a simple example of how you could implement an event for sending and not sending and subscribe to it
public class Connection
{
//Set up an event
public event EventHandler DataSending;
public event EventHandler DataNotSending
//This method will trigger the event for sending
private void OnDataSending()
{
if (DataSending!= null) { DataSending(this, EventArgs.Empty); }
}
//this method will trigger the event for finished sending
private void OnDataNotSending()
{
if (DataNotSending!= null) { DataNotSending(this, EventArgs.Empty); }
}
//This method performs your send logic
public void Send()
{
//Call your method that tells the event to be raised
OnDataSending();
//Then put your send code
OnDataNotSending(); //we're done!
}
}
This is how you use it in a consuming program
public class myForm
{
//This method is the one that sets up the
//instance and subscribes to the event
public myForm()
{
Connection con = new Connection();
con.DataSending += new EventHandler(con_DataSending);
con.DataNotSending += new EventHander(con_DataNotSending);
}
void con_DataSending(object sender, EventArgs e)
{
//Put your subscription logic here.
//Whatever you want to do in response to a send
}
void con_DataNotSending(object sender, EventArgs e)
{
//Put your subscription logic here.
//Respond to it not sending
}
}

Deadlock in C++/CLI Wrapper

I have a c++/cli wrapper class which grabs frames from a camera and sends them as events.
A WPF test application Starts the camera, and updates the images.
When I click Stop, it usually ends in a deadlock, on m->streamThread->Join(). I'm suspecting the problem has to do with the frame handling event in the WPF, rather than the wrapper code.
namespace WpfTestApp
{
public partial class Window1 : Window
{
private void OnFrameArrived(object sender, EventArgs e)
{
Action a = delegate
{
// this uses Imaging.CreateBitmapSourceFromMemorySection
// to copy the frame data to the image memory
m_colorImage.UpdateImage(e.Image);
};
Dispatcher.Invoke(a);
}
private void startBtn_Click(object sender, RoutedEventArgs e)
{
m_camera.FrameArrived += m_frameHandler;
m_camera.Start();
}
private void Stop()
{
m_camera.FrameArrived -= m_frameHandler;
m_camera.Stop();
}
}
}
// Camera.h
public ref class Camera
{
public:
delegate void FrameArrivedHandler(Object^ sender, DGEventArgs^ e);
event FrameArrivedHandler^ FrameArrived;
void Start();
void Stop();
private:
void StreamThreadWorker();
Thread^ m_streamThread;
bool m_isStreaming;
}
// Camera.cpp
void Camera::Start()
{
if (m_isStreaming)
return;
m_isStreaming = true;
m_streamThread = gcnew Thread(gcnew ThreadStart(this, &Camera::StreamThreadWorker));
m_streamThread->Start();
}
void Camera::Stop()
{
if (!m_isStreaming)
return;
m_isStreaming = false;
m_streamThread->Join(); // stuck here
}
void Camera::StreamThreadWorker()
{
EventArgs^ eventArgs = gcnew EventArgs();
while (m_isStreaming)
{
eventArgs->Image = Camera->GetImage();
FrameArrived(this, eventArgs);
}
}
likely what happens is: you click Stop, this gets handled in the WPF ui dispatcher thread. So the Join call is in the ui dispatcher thread. However this same thread is also responsible for drawing the frames (the invoked call to UpdateImage). As a result, the StreamThreadWorker is waiting on FrameArrived to finish, but that cannot finish because the thread is waiting for Stop to finish. There's your deadlock.
So in order to get the StreamThreadWorker to finish, it must not be blocked by Stop. An easy way to achive this is to stop the thread from within another thread:
void Camera::Stop()
{
...
gcnew Thread( gcnew ThreadStart( this, &Camera::DoStopThread ) )->Start();
}
void Camera::DoStopThread()
{
if( !m_streamThread.Join( 3000 ) )
HandleThreadDidNotStopInTimeError(); //notify listeners there's a serious problem
m_streamThread.Abort();
m_streamThread = null;
RaiseThreadStoppedEvent(); //notify listeners that the thread stopped
}

How do I make event callbacks into my win forms thread safe?

When you subscribe to an event on an object from within a form, you are essentially handing over control of your callback method to the event source. You have no idea whether that event source will choose to trigger the event on a different thread.
The problem is that when the callback is invoked, you cannot assume that you can make update controls on your form because sometimes those controls will throw an exception if the event callback was called on a thread different than the thread the form was run on.
To simplify Simon's code a bit, you could use the built in generic Action delegate. It saves peppering your code with a bunch of delegate types you don't really need. Also, in .NET 3.5 they added a params parameter to the Invoke method so you don't have to define a temporary array.
void SomethingHappened(object sender, EventArgs ea)
{
if (InvokeRequired)
{
Invoke(new Action<object, EventArgs>(SomethingHappened), sender, ea);
return;
}
textBox1.Text = "Something happened";
}
Here are the salient points:
You can't make UI control calls from a different thread than the one they were created on (the form's thread).
Delegate invocations (ie, event hooks) are triggered on the same thread as the object that is firing the event.
So, if you have a separate "engine" thread doing some work and have some UI watching for state changes which can be reflected in the UI (such as a progress bar or whatever), you have a problem. The engine fire's an object changed event which has been hooked by the Form. But the callback delegate that the Form registered with the engine gets called on the engine's thread… not on the Form's thread. And so you can't update any controls from that callback. Doh!
BeginInvoke comes to the rescue. Just use this simple coding model in all your callback methods and you can be sure that things are going to be okay:
private delegate void EventArgsDelegate(object sender, EventArgs ea);
void SomethingHappened(object sender, EventArgs ea)
{
//
// Make sure this callback is on the correct thread
//
if (this.InvokeRequired)
{
this.Invoke(new EventArgsDelegate(SomethingHappened), new object[] { sender, ea });
return;
}
//
// Do something with the event such as update a control
//
textBox1.Text = "Something happened";
}
It's quite simple really.
Use InvokeRequired to find out if this callback happened on the correct thread.
If not, then reinvoke the callback on the correct thread with the same parameters. You can reinvoke a method by using the Invoke (blocking) or BeginInvoke (non-blocking) methods.
The next time the function is called, InvokeRequired returns false because we are now on the correct thread and everybody is happy.
This is a very compact way of addressing this problem and making your Forms safe from multi-threaded event callbacks.
I use anonymous methods a lot in this scenario:
void SomethingHappened(object sender, EventArgs ea)
{
MethodInvoker del = delegate{ textBox1.Text = "Something happened"; };
InvokeRequired ? Invoke( del ) : del();
}
I'm a bit late to this topic, but you might want to take a look at the Event-Based Asynchronous Pattern. When implemented properly, it guarantees that events are always raised from the UI thread.
Here's a brief example that only allows one concurrent invocation; supporting multiple invocations/events requires a little bit more plumbing.
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public class MainForm : Form
{
private TypeWithAsync _type;
[STAThread()]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
public MainForm()
{
_type = new TypeWithAsync();
_type.DoSomethingCompleted += DoSomethingCompleted;
var panel = new FlowLayoutPanel() { Dock = DockStyle.Fill };
var btn = new Button() { Text = "Synchronous" };
btn.Click += SyncClick;
panel.Controls.Add(btn);
btn = new Button { Text = "Asynchronous" };
btn.Click += AsyncClick;
panel.Controls.Add(btn);
Controls.Add(panel);
}
private void SyncClick(object sender, EventArgs e)
{
int value = _type.DoSomething();
MessageBox.Show(string.Format("DoSomething() returned {0}.", value));
}
private void AsyncClick(object sender, EventArgs e)
{
_type.DoSomethingAsync();
}
private void DoSomethingCompleted(object sender, DoSomethingCompletedEventArgs e)
{
MessageBox.Show(string.Format("DoSomethingAsync() returned {0}.", e.Value));
}
}
class TypeWithAsync
{
private AsyncOperation _operation;
// synchronous version of method
public int DoSomething()
{
Thread.Sleep(5000);
return 27;
}
// async version of method
public void DoSomethingAsync()
{
if (_operation != null)
{
throw new InvalidOperationException("An async operation is already running.");
}
_operation = AsyncOperationManager.CreateOperation(null);
ThreadPool.QueueUserWorkItem(DoSomethingAsyncCore);
}
// wrapper used by async method to call sync version of method, matches WaitCallback so it
// can be queued by the thread pool
private void DoSomethingAsyncCore(object state)
{
int returnValue = DoSomething();
var e = new DoSomethingCompletedEventArgs(returnValue);
_operation.PostOperationCompleted(RaiseDoSomethingCompleted, e);
}
// wrapper used so async method can raise the event; matches SendOrPostCallback
private void RaiseDoSomethingCompleted(object args)
{
OnDoSomethingCompleted((DoSomethingCompletedEventArgs)args);
}
private void OnDoSomethingCompleted(DoSomethingCompletedEventArgs e)
{
var handler = DoSomethingCompleted;
if (handler != null) { handler(this, e); }
}
public EventHandler<DoSomethingCompletedEventArgs> DoSomethingCompleted;
}
public class DoSomethingCompletedEventArgs : EventArgs
{
private int _value;
public DoSomethingCompletedEventArgs(int value)
: base()
{
_value = value;
}
public int Value
{
get { return _value; }
}
}
}
As the lazy programmer, I have a very lazy method of doing this.
What I do is simply this.
private void DoInvoke(MethodInvoker del) {
if (InvokeRequired) {
Invoke(del);
} else {
del();
}
}
//example of how to call it
private void tUpdateLabel(ToolStripStatusLabel lbl, String val) {
DoInvoke(delegate { lbl.Text = val; });
}
You could inline the DoInvoke inside your function or hide it within separate function to do the dirty work for you.
Just keep in mind you can pass functions directly into the DoInvoke method.
private void directPass() {
DoInvoke(this.directInvoke);
}
private void directInvoke() {
textLabel.Text = "Directly passed.";
}
In many simple cases, you can use the MethodInvoker delegate and avoid the need to create your own delegate type.

Categories