I am using System.Threading.Timer to create a timer that prints a string to a serial port and then reads from another serial port every second. I am trying to do this by sending arguments to my TimerCallback function. Below is my code where the timer is initialized and the code for the callback function.
Initialization:
TimerCallback tcb = Timer_func(buff_out, send_port, recv_port);
AutoResetEvent autoEvent = new AutoResetEvent(false);
Timer aTimer = new Timer(tcb,autoEvent,1000,1000);
Callback function:
public static TimerCallback Timer_func(string buff_out, SerialPort send_port, SerialPort recv_port)
{
string buff_in;
send_port.WriteLine(buff_out);
buff_in = recv_port.ReadLine();
Console.WriteLine(buff_in);
}
The initialization occurs in the Main() function, and both functions are in the same class.
When I compile the code as is I recieve error CS0161: "not all code paths return a value". In attempts to remedy this I've added return 1; to the end of that function but then I recieve error CS0029: "cannot explicitly convert type 'int' to 'System.Threading.Timer'.
What am I doing wrong, and how can I fix it. (New to C#). Thank you in advance!
You're misunderstanding delegates.
TimerCallback is a delegate type – a type that can hold a function.
TimerCallback can only hold functions with the signature
void MethodName(Object state)
When you write
public static TimerCallback Timer_func(...) { ... }
You just declared a function that returns a TimerCallback delegate.
Thus, your function must return a function that matches TimerCallback.
You can do that using an anonymous delegate:
return delegate (object state) {
string buff_in;
send_port.WriteLine(buff_out);
buff_in = recv_port.ReadLine();
Console.WriteLine(buff_in);
};
Related
My situation: I'm creating a library using C# that will be called from Excel using VBA code. There's a C# method "SubscribeCallBack" which will receive an address of a VBA Procedure (Function Pointer) and marshal the function pointer into a C# delegate. Let me explain more:
In the C# library there's a variable to store a typed delegate:
public delegate bool TDelegate([MarshalAs(UnmanagedType.BStr)]string str);
TDelegate CallBack = null;
This delegate will run upon some event:
someObj.SomeEvent += (object sender, EventArgs args) => {
if (CallBack != null)
CallBack(someString);
};
And a method exposed to VBA code to set the CallBack:
public void SetCallBack(int callBackAddress) {
try {
CallBack = (TDelegate)Marshal.GetDelegateForFunctionPointer(
new IntPtr(address), typeof(TDelegate));
}
}
Now after the compiled C# library is loaded as a Excel AddIn, I can call C# methods using Application.Run(). I can write this:
Application.Run("SetCallBack", AddressOf VBACallBack)
Public Function VBACallBack(ByVal str As String) As Boolean
Cells(1, 1).Value = str
MsgBox "VBACallBack Running"
VBACallBack = True
End Function
Now things work as expected: I can see VBACallBack got executed when it should be.
Now finally comes the question: I put [MarshalAs(UnmanagedType.Bstr)]string as C# delegate parameter so that the VBA Function with a single string argument can be Marshaled to this typed delegate. Now I need to pass a Function from VBA like this into a C# delegate:
Function(stringArray() As String) As Boolean
taking a String array (or any other thing containing an ordered list of String to make it work)
How exactly can I do this? I tried with [MarshalAs(UnmanagedType.AsAny)]string[] and [MarshalAs(UnmanagedType.LPArray)]string[] both are not working.
New to C#. Is it possible to have delegates that point to the function that have "preset" argument that is set by me ?
public delegate void Del(string message);
static void Notify(string name)
{
Console.WriteLine("Notification received for: {0}", name);
}
// Looking for something similar, but code below gives me an error
// Del del5 = Notify("http://stackoverflow.com");
Sure - you can have lambda that call that function with whatever arguments you want. In your case us seem to ignore argument altogether which by convention is written as _ as argument name:
Del del5 = _ => Notify("http://stackoverflow.com");
del5("whatever - ignored anyway"); // always calls Notify("http://stackoverflow.com")
More genric case would be to have function with many (i.e.2) parameters and than specify first one to be fixed value in the delegate:
static void Notify2(string siteName, string message) {...}
Del messageToStackOverflow = message =>
Notify2 ("http://stackoverflow.com", message);
// calls Notify2 adding first argument SO:
// Notify2("http://stackoverflow.com", "Useful message to SO")
messageToStackOverflow("Useful message to SO");
In general this called partial function application when you fix some arguments to particular values.
No it is not possible to do it like this, because this would assign the result (void) of the Notify method call to del5. Default parameter values are not allowed for delegates.
I'm trying to call buildRangedJobCache with SelectionRange S as the passed in parameter, But the Compiler(visual studio 2010) gives the error: Method Name Expected below is the call that gives issue:
private void retrieveSeveralDaysJobs(SelectionRange S)
{
ignoreUpdates = false;
this.SetStatus(DataLogUIStrings.strRetrievingJobInformation);
Thread buildIndexThread = new Thread(new ThreadStart(buildRangedJobCache(S)));
buildIndexThread.Priority = ThreadPriority.Lowest;
buildIndexThread.Start();
}
and here is the function buildRangedJobCache(SelectionRange S):
private void buildRangedJobCache(SelectionRange S)
{
this.Cursor = Cursors.AppStarting;
try
{
if (DataStore == null)
{ throw new Exception("Error: DataStore is null, Unable to retrieve jobs."); }
lock (((ICollection)jobs).SyncRoot)
{
for (DateTime Day = S.Start; Day <= S.End; Day.AddDays(1))
{
this.RangeJobs.AddRange(DataStore.GetJobsListForDay(JobDateToDisplay.GetValueOrDefault(DateTime.Today)));
}
}
this.SetStatus(string.Format(DataLogUIStrings.strRetrievedSummaryInformation, this.jobs.Count));
}
catch (Exception e)
{
Log.Write(e);
}
this.Cursor = Cursors.Default;
}
also I've linked to here: Delegate: Method name expected error
as this solution didn't work for me.
**update: apparently it isn't clear, the solution of putting:
Thread buildIndexThread = new Thread(new ThreadStart(buildRangedJobCache));
does the same issue.
Pass only method name when creating delegate:
Thread buildIndexThread = new Thread(new ThreadStart(buildRangedJobCache));
Also ThreadStart delegate should not receive any arguments. It is defined as
public delegate void ThreadStart();
So, your buildRangedJobCache method signature do not match ThreadStart delegate signature. If you want to pass some parameters to thread, you should use ParameterizedThreadStart delegate, which accepts parameter of type object:
private void retrieveSeveralDaysJobs(SelectionRange range)
{
ignoreUpdates = false;
this.SetStatus(DataLogUIStrings.strRetrievingJobInformation);
// pass ParameterizedThreadStart delegate
Thread buildIndexThread = new Thread(BuildRangedJobCache);
buildIndexThread.Priority = ThreadPriority.Lowest;
buildIndexThread.Start(range); // provide parameter for thread
}
private void BuildRangedJobCache(Object obj)
{
SelectionRange range = (SelectionRange)obj; // cast to your type
// code
}
The Thread constructor requires a delegate (either ThreadStart or ParametrizedThreadStart). You're trying to create the ThreadStart delegate, but you can create a delegate out of a method, not method invocation expression.
So, if your method didn't have a parameter, the following would work:
new Thread(new ThreadStart(buildRangedJobCache));
and so would (because the compiler can infer which delegate are you creating):
new Thread(buildRangedJobCache);
If you need to pass a parameter to your method, you can use ParametrizedThreadStart and the overload of Start() that takes a parameter. But this means you have to change your method to have object parameter and cast it to your type inside the method.
I think a better option would be to use a lambda:
new Thread(() => buildRangedJobCache(S));
This creates an anonymous method that matches ThreadStart and remembers the variable S. This way, you don't need the signature of your method and you also don't need any casting.
I'm learning socket programming and I have the following function:
public void OnDataReceived(IAsyncResult asyn)
and this is how the callback gets set:
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
The problem is I need to pass another argument to OnDataReceived callback function, how can I do this? I'm trying to make a simple tcp server and I need to track from which client the data is coming from. Any tips? Thanks!
I'm going to presume you're using System.Net.Sockets.Socket here. If you look at the overloads of BeginReceive you'll see the object parameter (named state). You can pass an arbitrary value as this parameter and it will flow through to your AsyncCallback call back. You can then acess it using the AsyncState property of IAsyncResult object passed into your callback. Eg;
public void SomeMethod() {
int myImportantVariable = 5;
System.Net.Sockets.Socket s;
s.BeginReceive(buffer, offset, size, SocketFlags.None, new new AsyncCallback(OnDataReceived), myImportantVariable);
}
private void OnDataReceived(IAsyncResult result) {
Console.WriteLine("My Important Variable was: {0}", result.AsyncState); // Prints 5
}
This is a problem I prefer to solve with anonymous delegates:
var someDataIdLikeToKeep = new object();
mySocket.BeginBlaBla(some, other, ar => {
mySocket.EndBlaBla(ar);
CallSomeFunc(someDataIdLikeToKeep);
}, null) //no longer passing state as we captured what we need in callback closure
It saves having to cast a state object in the receiving function.
When you call BeginReceive, you can pass any object as its last parameter. The same object will be made available to your callback through IAsyncResult's AsyncState property.
As MrMDavidson mentioned.
If you look at the overloads of BeginReceive you'll see the object parameter (named state)
You could pass an object array of your desired parameters to the state parameter and then deal with them later in the callback method.
client.BeginConnect(ipEndPoint, new AsyncCallback(ConnectedCallback), new object[] { parameter1, parameter2});
Based on the following question, I found some odd behaviour of the c# compiler.
The following is valid C#:
static void K() {}
static void Main()
{
var k = new Action(new Action(new Action(K))));
}
What I do find strange is the compiler 'deconstructing' the passed delegate.
The ILSpy output is as follows:
new Action(new Action(new Action(null, ldftn(K)), ldftn(Invoke)).Invoke);
As one can see, it automatically decides to use the Invoke method of the delegate. But why?
As it is, the code is unclear. Do we have a triply-wrapped delegate (actual) or is the inner delegate just 'copied' to the outer ones (my initial thought).
Surely if the intent was like the compiler emitted the code, one should have written:
var k = new Action(new Action(new Action(K).Invoke).Invoke);
Similar to the decompiled code.
Can anyone justify the reason for this 'surprising' transformation?
Update:
I can only think of one possible use-case for this; delegate type conversion. Eg:
delegate void Baz();
delegate void Bar();
...
var k = new Baz(new Bar( new Action (K)));
Perhaps the compiler should emit a warning if the same delegate types are used.
The spec (section 7.6.10.5) says:
The new delegate instance is initialized with the same invocation list as the delegate instance given by E.
Now suppose the compiler translated it to something similar to your suggestion of:
new Action( a.Target, a.Method)
That would only ever create a delegate with an invocation list of a single method call. For a multi-cast delegate, it would violate the spec.
Sample code:
using System;
class Program
{
static void Main(string[] args)
{
Action first = () => Console.WriteLine("First");
Action second = () => Console.WriteLine("Second");
Action both = first + second;
Action wrapped1 =
(Action) Delegate.CreateDelegate(typeof(Action),
both.Target, both.Method);
Action wrapped2 = new Action(both);
Console.WriteLine("Calling wrapped1:");
wrapped1();
Console.WriteLine("Calling wrapped2:");
wrapped2();
}
}
Output:
Calling wrapped1:
Second
Calling wrapped2:
First
Second
As you can see, the real behaviour of the compiler matches the spec - your suggested behaviour doesn't.
This is partly due to the somewhat odd "sometimes single-cast, sometimes multi-cast" nature of Delegate, of course...
When you try to treat a delegate as a method, the compiler actually uses the delegate's Invoke() method. So, for example, the two lines below compile to the exact same IL (both call Invoke()):
k();
k.Invoke();
I assume the oddity you're seeing is a consequence of this. The delegate constructor expects a method (or rather, a method group), but it gets a delegate instead. So it treats it as a method and uses the Invoke() method.
As for the meaning, it is delegate that calls delegate that calls the actual method. You can verify this yourself by accessing the delegate's Method and Target properties. In the case of the outer-most delegate, Method is Action.Invoke and Target the inner delegate.
delegate is a class
Action delegate has a constructor like so
public extern Action(object #object, IntPtr method);
Since K is a static method there is no need to pass object to inner most action instance as first argument and hence it passes null
Since second argument is pointer to function therefore it passes pointer of K method using ldftn function
for the remaining Action instances the object is passed is inner Action and the second parameter is the Invoke method since when you call a delegate you're actually calling the Invoke method
Summary
var action = new Action(K) => Action action = new Action(null, ldftn(K))
new Action(action) => new Action(action, ldftn(Action.Invoke))
I hope this explains what is happening?