Generalize Invoke function and delegate - c#

How can I factor those two function/delegate into one general function and delegate ?
Is there an easy way to do this ?
public TabControl tab;
public Label devlog;
delegate void tabHandlerCallback(bool e);
public void tabHandler(bool e)
{
if (tab.InvokeRequired)
{
tab.Invoke(new tabHandlerCallback(tabHandler), new object[] { e });
}
else
{
tab.Enabled = e;
}
}
delegate void devHandlerCallback(string e);
public void devHandler(string e)
{
if (devlog.InvokeRequired)
{
devlog.Invoke(new devHandlerCallback(devHandler), new object[] { e });
}
else
{
devlog.Text = e;
}
}

you can use following code
public delegate void InvokeDelegate();
//T_Elapsed is a thread and controls required invoke
private void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.BeginInvoke(new InvokeDelegate(InvokeMethodLabel));
this.BeginInvoke(new InvokeDelegate(InvokeMethodProgressBar));
}
void InvokeMethodLabel()
{
myLabel.Text = "Test Label";
}
void InvokeMethodProgressBar()
{
progressBar.Value = (int)(progressBar.Value * 2);
}

Here is how I did it :
delegate void controlHandlerCallback(object control, object param, string field = "Text");
public void controlHandler(object control, object param, string field="Text")
{
if (((Control)control).InvokeRequired)
{
((Control)control).Invoke(new controlHandlerCallback(controlHandler), new object[] { control, param,field });
}
else
{
PropertyInfo propertyInfo = control.GetType().GetProperty(field);
propertyInfo?.SetValue(control, param);
}
}

You can make a function that can run the necessary code either directly, or by invoking.
private void InvokeIfNecessary(Control control, Action action)
{
if(control.InvokeRequired)
control.Invoke(action);
else
action();
}
// use it like this
public void devHandler(string e)
{
InvokeIfNecessary(() => devlog.Text = e);
}
public void tabHandler(bool e)
{
InvokeIfNecessary(() => tab.Enabled = e);
}

Related

How to pass a parameter to a timer event

I am trying to implement a timer as per the below code. I want to pass a parameter to the timer event. I have used below anonymous function approach.
However this would only pass only the first parameter to the OnTimerElapsedEvent. Can someone please advise?
class Program
{
static void Main(string[] args)
{
ClassA obj = new ClassA();
Console.WriteLine("Start" + " " + System.DateTime.Now);
obj.SampleMethod("hello", 3000);
Thread.Sleep(4000);
obj.SampleMethod("world", 6000);
Console.ReadKey();
}
}
class ClassA
{
private System.Timers.Timer tTimer;
public void SampleMethod(string strParam, int iTimerInterval)
{
if (tTimer == null)
{
tTimer = new System.Timers.Timer();
tTimer.Elapsed += (sender, e) =>
OnTimerElapsedEvent(sender, e, strParam);
}
tTimer.Interval = iTimerInterval;
tTimer.Enabled = true;
tTimer.Start();
}
private void OnTimerElapsedEvent(object source, ElapsedEventArgs e, string strParam)
{
//use strParam value here
Console.WriteLine(strParam + " " + System.DateTime.Now);
if (strParam == "world")
{
tTimer.Stop();
tTimer.Enabled = false;
}
}
}
You can inherit the Timer class to provide a parameter in the constructor like below. Or you can inherit the Timer class and provide a property:
[TestClass]
public class TimerTester
{
[TestMethod]
public void TestYourTimer()
{
var timer1 = new TimerWithParameter("param1");
timer1.Interval = 1000;
timer1.ElapsedEvent += Timer_ElapsedEvent;
timer1.Start();
var timer2 = new TimerWithParameter("param2");
timer2.Interval = 1300;
timer2.ElapsedEvent += Timer_ElapsedEvent;
timer2.Start();
Thread.Sleep(5000);
}
private void Timer_ElapsedEvent(object source, ElapsedEventArgs e, string strParam)
{
Debug.WriteLine(strParam);
}
}
public delegate void ElapsedWithParameterDelegate(object source, ElapsedEventArgs e, string strParam);
public class TimerWithParameter:Timer
{
private readonly string _strParam;
public event ElapsedWithParameterDelegate ElapsedEvent;
public TimerWithParameter(string strParam)
{
_strParam = strParam;
this.Elapsed += TimerWithParameter_Elapsed;
}
private void TimerWithParameter_Elapsed(object sender, ElapsedEventArgs e)
{
ElapsedEvent?.Invoke(this, e, _strParam);
}
}

pjsip c#, System.AccessViolationException on answering an incoming call on an separated thread

In the overrided void onIncomingCall I open a new Background thread which shows a new (Popup) Form.
I try to pickup or decline the Call in this Form but then I get an System.AccessViolationException.
it seems that the current call object is locked and cannot be accessed from another Form.
If I use the currentcall.answer(prm) in the onIncomingCall void then the call is established successfully (without another Form and thread).
public class myaccount : Account
{
public override void onIncomingCall(OnIncomingCallParam prm)
{
Call call = new Call(this, prm.callId);
CallOpParam param = new CallOpParam();
param.statusCode = pjsip_status_code.PJSIP_SC_RINGING;
param.statusCode = pjsip_status_code.PJSIP_SC_OK;
pjsipfunctions.currentparam = param;
pjsipfunctions.currentcall = call;
var thread = new Thread(() =>
{
ShowPopup(call,prm.callId.ToString());
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
// Thread myCallingThread = new Thread(new ThreadStart(ShowPopup));
//myCallingThread.SetApartmentState(ApartmentState.STA);
//myCallingThread.IsBackground = true;
//myCallingThread.Start();
}
public void ShowPopup(Call myCall,string call_id)
{
IncommingCallPopup win = new IncommingCallPopup(ref myCall, call_id );
win.Show();
System.Windows.Threading.Dispatcher.Run();
}
}
#####################################
public IncommingCallPopup(ref Call info, string callid)
{
currentCall = info;
Callid = callid;
CurrentCall = currentCall;
Prm.statusCode = pjsip_status_code.PJSIP_SC_RINGING;
InitializeComponent();
labelCallId.Content = callid;
}
private void rejectcall(object sender, RoutedEventArgs e)
{
Prm.statusCode = pjsip_status_code.PJSIP_SC_DECLINE;
CurrentCall.hangup(Prm);
}
private void transfercall(object sender, RoutedEventArgs e)
{
}
private void takecall(object sender, RoutedEventArgs e)
{
Prm.statusCode = pjsip_status_code.PJSIP_SC_OK;
try
{
CurrentCall.answer(Prm);
}
catch(Exception ex)
{
}
}
After crazy searching and trying some things i've figured it out.
Every Thread must registered in the Endpoint that you can hangup, pickup or transfer your call in another Class(Window).
All you need is to write this Method in a Public class and call this void everytime you call your void from another window ->
public void callpopup(String number) {
checkThread();
//answer, decline or something else
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static void checkThread()
{
try
{
if (ep != null && !ep.libIsThreadRegistered())
ep.libRegisterThread(Thread.CurrentThread.Name);
}
catch (Exception e)
{
}
}

Publish and subscribe events in silverlight

I am trying to understand a piece of code in a legacy silverlight application.In this code as you can see user can publish an event and subscribe to that event.
while publishing event
Messenger.Publish<ErrorInformationData>(MessageConstant.ShowMessageTechnicalError,
new ErrorInformationData(ServiceOperationName.ClaimsService_GetClaim, ServiceOperationOccurence.DataServiceUI));
then subscribing to that event
Messenger.Subscribe<ErrorInformationData>(
this,
MessageConstant.ShowMessageTechnicalError,
(result) =>
{
Messenger.Publish(MessageConstant.ShowMessage,
new MessageData
{
Title = "Common$TechnicalError",
MessageText = "Common$TechnicalErrorDetail",
TextParameters = new object[] { result.OperationErrorCode.ToString() },
MessageType = MessageData.MessageTypes.OK,
OKAction = () =>
{
HtmlPage.Window.Navigate(new Uri("", UriKind.Relative));
},
MessageLevel = MessageData.MessageLevels.Error
}
);
}
);
Question is why do I need to use this framework where instead I can simply invoke a method.Also can anyone point to any documentation/tutorial regarding this communication.
Thanks #Nikosi for pointer, after more investigation I have found what's going on under the hood.
So there is a IMessanger interface which contains signature of publish,subscribe and unsubscribe method.
public interface IMessanger : IDisposable
{
void Subscribe(IReceiver receiver, int messageId);
void Publish<TEventArgs>(object sender, TEventArgs e, int messageId)
where TEventArgs : EventArgs;
void Unsubscribe(IReceiver receiver, int messageId);
}
Now we define a class Messanger which implements the interface.
public sealed class Messanger : IMessanger
{
private readonly Dictionary<int, List<IReceiver>> messageIdToReceiver;
public Messanger()
{
this.messageIdToReceiver = new Dictionary<int, List<IReceiver>>();
}
public void Subscribe(IReceiver receiver, int messageId)
{
List<IReceiver> receivers;
if (this.messageIdToReceiver.TryGetValue(messageId, out receivers))
{
receivers.Add(receiver);
}
else
{
this.messageIdToReceiver.Add(messageId, new List<IReceiver>() { receiver });
}
}
public void Publish<TEventArgs>(object sender, TEventArgs e, int messageId)
where TEventArgs : EventArgs
{
List<IReceiver> receivers;
if (this.messageIdToReceiver.TryGetValue(messageId, out receivers))
{
foreach (IReceiver receiver in receivers)
{
IReceiver<TEventArgs> receiverToReceive = receiver as IReceiver<TEventArgs>;
if (receiverToReceive != null)
{
receiverToReceive.Receive(sender, e, messageId);
}
}
}
}
public void Unsubscribe(IReceiver receiver, int messageId)
{
List<IReceiver> receivers;
if (this.messageIdToReceiver.TryGetValue(messageId, out receivers))
{
if (receivers.Count > 1)
{
receivers.Remove(receiver);
}
else if(receivers.Count == 1)
{
this.messageIdToReceiver.Remove(messageId);
}
}
}
public void Dispose()
{
this.messageIdToReceiver.Clear();
}
}
public interface IReceiver<TEventArgs> : IReceiver
where TEventArgs : EventArgs
{
void Receive(object sender, TEventArgs e, int messageId);
}
public interface IReceiver : IDisposable
{
}
Now we can see the usage of the above,Defined two classes one is publishing the event and other one is receiving the event.
public class PresenterA : IReceiver<EventArgs>, IDisposable
{
readonly IMessanger messanger;
public PresenterA(IMessanger messanger)
{
this.messanger = messanger;
this.messanger.Subscribe(this, (int)PubSubMsg.AppInstl);
}
public void Receive(object sender, EventArgs e, int messageId)
{
if ((PubSubMsg)messageId == PubSubMsg.AppInstl)
{
//Now that you received the message, update the UI, etc...
}
}
public void Dispose()
{
this.messanger.Unsubscribe(this, (int)PubSubMsg.AppInstl);
}
}
public class PresenterB
{
readonly IMessanger messanger;
public PresenterB(IMessanger messanger)
{
this.messanger = messanger;
}
public void btnApplicationRemove(object sender, EventArgs e)
{
//Do what you need to do and then publish the message
this.messanger.Publish<EventArgs>(this, e, (int)PubSubMsg.AppInstl);
}
}
public enum PubSubMsg
{
AppInstl = 1
}

initialising a delegate with a string

Is there any way to initialise a delegate with a string? I.e. you won't know the name of the function that needs to be called at runtime? Or I'm guessing there is a better way of doing this?
delegate void TestDelegate(myClass obj);
void TestFunction()
{
TestDelegate td = new TestDelegate(myFuncName); // works
TestDelegate td = new TestDelegate("myFuncName"); // doesn't work
}
Update
Is is the code I currently have which is not working
class Program
{
static void Main(string[] args)
{
Bish b = new Bish();
b.MMM();
Console.Read();
}
}
class Bish
{
delegate void TestDelegate();
public void MMM()
{
TestDelegate tDel = (TestDelegate)this.GetType().GetMethod("PrintMe").CreateDelegate(typeof(TestDelegate));
tDel.Invoke();
}
void PrintMe()
{
Console.WriteLine("blah");
}
}
You can create a dynamic delegate this way
class Bish
{
delegate void TestDelegate();
delegate void TestDelegateWithParams(string parm);
public void MMM()
{
TestDelegate tDel = () => { this.GetType().GetMethod("PrintMe").Invoke(this, null); };
tDel.Invoke();
TestDelegateWithParams tDel2 = (param) => { this.GetType().GetMethod("PrintMeWithParams").Invoke(this, new object[] { param }); };
tDel2.Invoke("Test");
}
public void PrintMe()
{
Console.WriteLine("blah");
}
public void PrintMeWithParams(string param)
{
Console.WriteLine(param);
}
}

Passing a method as a parameter with parameters

So I know how to do:
void PrintFoo () { Console.Write("Foo");}
void DoSomething (Action methodToCall) { methodToCall();}
void Main () { DoSomething(PrintFoo); }
What I want to do:
void PrintFoo (string fooToPrint) { Console.Write(fooToPrint);}
void DoSomething (Action methodToCall) { methodToCall();}
void Main () { DoSomething(PrintFoo("Foo bar baz")); }
Basically call an action WITH Parameters
Use a lambda expression:
void PrintSomething(string stringToPrint) { Console.Write(stringToPrint); }
void DoSomething(Action methodToCall) { methodToCall(); }
void Main()
{
DoSomething(() => PrintSomething("Message"));
}
You may also define actions to require parameter types for the callback.
public void DoSomething(Action<string> Callback){
var result = getMyString();
Callback(result);
}
public void DoSomething(Action<string> CallBack, List<string> Parms){
var sb = new StringBuilder();
Parms.ForEach(p=> sb.Append(Parse(p));
Callback(sb.ToString());
}

Categories

Resources