C# callback on new thread - c#

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)));
}

Related

WCF callback not working as expected

I made a WCF service which makes a callback to a WPF client. I just show the progress in a textbox in the WPF client. What I got first is cross thread operation not valid. Then I modified the client side code and implemented using methods such as Invoke() and BeginInvoke(). Now the client side code shows only the value 100%. Actually it should display the values from 0-100%. Any solutions?
The code at wcf service:
namespace ReportService
{
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant,InstanceContextMode=InstanceContextMode.Single)]
public class Report : IReportService
{
public void ProcessReport()
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(1000);
OperationContext.Current.GetCallbackChannel<IReportCallback>().ReportProgress(i);
}
}
}
}
Code at client:
namespace Report
{
[CallbackBehavior(UseSynchronizationContext=false)]
public partial class Form1 : Form,ReportService.IReportServiceCallback
{
delegate void delSetTxt(int percentCompleted);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
InstanceContext ic= new InstanceContext(this);
ReportService.ReportServiceClient client = new ReportService.ReportServiceClient(ic);
client.ProcessReport();
}
public void ReportProgress(int percentCompleted)
{
// this.Invoke(new Action(() => { this.textBox1.Text = percentCompleted.ToString(); }));
Thread t = new Thread(() => setTxt(percentCompleted));
t.Start();
}
public void setTxt(int percentCompleted)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new delSetTxt(setTxt), new object[] { percentCompleted });
return;
}
this.textBox1.Text = percentCompleted.ToString() + " % complete";
}
}
}
When the call is made to the service, the GUI thread is stuck in the button_click method.
So the GUI thread must not be frozen.
There are (at least) two solutions that work, I tested them :
Put [OperationContract(IsOneWay = true)] both on the server and the callback operation
Put [OperationContract(IsOneWay = true)] on the callback operation and don't lock GUI thread with await/async:
private async void button1_Click(object sender, EventArgs e)
{
InstanceContext ic = new InstanceContext(this);
ReportServiceClient client = new ReportServiceClient(ic);
await client.ProcessReportAsync();
//client.ProcessReport();
}
Good luck

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
}
}

Return feedback from an event which is being waited on

In it's simplicity what I am trying to do is handle "Doing Something" by firing off a process on a seperate thread to do what I need to do and waiting for an event to be raised to say "I have finished doing what I need to do". In the EventArgs though I will have a property for any errors which may be encountered during the process. Here is a simplified example of my situation.
public class MessageHandler
{
private AutoResetEvent MessageHasSent = new AutoResetEvent(false);
public void SendMessage()
{
MessageSender ms = new MessageSender();
ms.MessageSent += new EventHandler<MessageSentEventArgs>(MessageHandler_MessageSent);
Thread t = new Thread(ms.Send());
t.Start();
MessageHasSent.WaitOne();
//Do some check here
//Same again but for "Message recieved"
}
void MessageHandler_MessageSent(object sender, MessageSentEventArgs e)
{
if (e.Errors.Count != 0)
{
//What can I do here to return to the next step after waitone?
}
else
MessageHasSent.Set();
}
}
public class MessageSender
{
public event EventHandler<MessageSentEventArgs> MessageSent;
public void Send()
{
//Do some method which could potentiallialy return a List<Error>
MessageSent(this, new MessageSentEventArgs() { Errors = new List<Error>() });
}
}
public class Error { }
public class MessageSentEventArgs : EventArgs
{
public List<Error> Errors;
}
Essentially once the event has been raised from Send the code will continute, however I want some way of the event giving feedback, potentially using the MessageHasSent. I have tried different methods, I thought if I called Close instead of Set it would perhaps allow me to access something such as IsClosed. You could throw an exception or set a flag outside of the scope of the event to check but I feel like this is dirty.
Any suggestions?
Using the TPL isn't applicable in my case as I am using .NET 3.5.
Since it seems that this entire section of code is already running in a background thread, and you're doing nothing more than starting up a new thread just so that you can wait for it to finish, you'd be better off just calling Send directly, rather than asynchronously.
You don't need to fire off an event when you're completed.
You don't need to signal the main thread when it needs to continue.
You don't need to log the exceptions in a List, you can just throw them and catch them in SendMessage with a try/catch block.
This will do what you want:
public class MessageHandler
{
private AutoResetEvent MessageHasSent = new AutoResetEvent(false);
private bool IsSuccess = false;
public void SendMessage()
{
MessageSender ms = new MessageSender();
ms.MessageSent += new EventHandler<MessageSentEventArgs>(MessageHandler_MessageSent);
Thread t = new Thread(ms.Send());
t.Start();
MessageHasSent.WaitOne();
if(IsSuccess)
//wohooo
else
//oh crap
//Same again but for "Message recieved"
}
void MessageHandler_MessageSent(object sender, MessageSentEventArgs e)
{
IsSuccess = e.Errors.Count == 0;
MessageHasSent.Set();
}
}
public class MessageSender
{
public event EventHandler<MessageSentEventArgs> MessageSent;
public void Send()
{
//Do some method which could potentiallialy return a List<Error>
MessageSent(this, new MessageSentEventArgs() { Errors = new List<Error>() });
}
}
public class Error { }
public class MessageSentEventArgs : EventArgs
{
public List<Error> Errors;
}

Question on threading in C#

I have a Windows Forms application at the moment, and I want to create a new thread and run a method on another class that accepts an input.
For example
public partial class Form1: Form {
SerialPort serialInput;
// I want to create a new thread that will pass the parameter serialInput into the method
// SMSListener on another class and run the method contionously on the background.
}
class SMS
{
public void SMSListener(SerialPort serial1)
{
serial1.DataReceived += port_DataRecieved;
}
private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
// Other codes
}
}
How do I perform this in C#? I have seen numerous examples on the web, and most of them run the method on the same class with no parameters, but none that suits my requirements.
Perhaps a Background Worker could help you?
It is a bit hard to understand what you are aiming at.
public class Runner
{
private readonly BackgroundWorker _worker = new BackgroundWorker();
public Runner()
{
_worker.DoWork += WorkerDoWork;
}
public void RunMe(int payload)
{
_worker.RunWorkerAsync(payload);
}
static void WorkerDoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
// Work
System.Threading.Thread.Sleep((int)e.Argument);
}
}
}
I am not an expert on Multithreading but to the best of my knowledge you can only start threads on methods that accept an object parameter and return void. So in order to achieve that for your problem (don't shoot me down if there is a better approach!) I would do something like
public partial class Form1: Form {
SerialPort serialInput;
// I want to create a new thread that will pass the parameter serialInput into the method
// SMSListener on another class and run the method contionously on the background.
SMS sms = new SMS();
Thread t = new Thread(sms.SMSListenerUntyped);
t.Start(serialInput);
}
class SMS
{
public void SMSListenerUntyped(object serial1) {
if (serial1 is SerialPort) //Check if the parameter is correctly typed.
this.SMSListener(serial1 as SerialPort);
else
throw new ArgumentException();
}
public void SMSListener(SerialPort serial1)
{
serial1.DataReceived += port_DataRecieved;
}
private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
// Other code.
}
How about just use the ThreadPool directly with a anonymous method allowing you to access your surrounding locals?
public void OnButtonClick(object sender, EventArgs e)
{
SerialPort serialInput = this.SerialInput;
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
SmsListener listener = new SmsListener(serialInput);
});
}

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