Consider this Reactive Extensions snippet (ignore the practicality of it):
return Observable.Create<string>(async observable =>
{
while (true)
{
}
});
This does not compile with Reactive Extensions 2.2.5 (using NuGet Rx-Main package). It fails with:
Error 1 The call is ambiguous between the following methods or properties: 'System.Reactive.Linq.Observable.Create<string>(System.Func<System.IObserver<string>,System.Threading.Tasks.Task<System.Action>>)' and 'System.Reactive.Linq.Observable.Create<string>(System.Func<System.IObserver<string>,System.Threading.Tasks.Task>)'
However, adding a break anywhere in the while loop fixes the compilation error:
return Observable.Create<string>(async observable =>
{
while (true)
{
break;
}
});
The problem can be reproduced without Reactive Extensions at all (easier if you want to try it without fiddling with Rx):
class Program
{
static void Main(string[] args)
{
Observable.Create<string>(async blah =>
{
while (true)
{
Console.WriteLine("foo.");
break; //Remove this and the compiler will break
}
});
}
}
public class Observable
{
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, Task> subscribeAsync)
{
throw new Exception("Impl not important.");
}
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, Task<Action>> subscribeAsync)
{
throw new Exception("Impl not important.");
}
}
public interface IObserver<T>
{
}
Ignoring the Reactive Extensions part of it, Why does adding break help the C# compiler resolve the ambiguity? How can this be described with the rules of overload resolution from the C# specification?
I'm using Visual Studio 2013 Update 2 targeting 4.5.1.
It's easiest to just pull out async as well as the lambdas here, as it emphasizes what's going on. Both of these methods are valid and will compile:
public static void Foo()
{
while (true) { }
}
public static Action Foo()
{
while (true) { }
}
However, for these two methods:
public static void Foo()
{
while (true) { break; }
}
public static Action Foo()
{
while (true) { break; }
}
The first compiles, and the second does not. It has a code path that doesn't return a valid value.
In fact, while(true){} (along with throw new Exception();) is an interesting statement in that it is the valid body of a method with any return type.
Since the infinite loop is a suitable candidate for both overloads, and neither overload is "better", it results in an ambiguity error. The non-infinite loop implementation only has one suitable candidate in overload resolution, so it compiles.
Of course, to bring async back into play, it is actually relevant in one way here. For the async methods they both always return something, whether it's a Task or a Task<T>. The "betterness" algorithms for overload resolution will prefer delegates that return a value over void delegates when there is a lambda that could match either, however in your case the two overload both have delegates that return a value, the fact that for async methods returning a Task instead of a Task<T> is the conceptual equivalent of not returning a value isn't incorporated into that betterness algorithm. Because of this the non-async equivalent wouldn't result in an ambiguity error, even though both overloads are applicable.
Of course it's worth noting that writing a program to determine if an arbitrary block of code will ever complete is a famously unsolvable problem, however, while the compiler cannot correctly evaluate whether every single snippet will complete, it can prove, in certain simple cases such as this one, that the code will in fact never complete. Because of this there are ways of writing code that will clearly (to you and me) never complete, but that the compiler will treat as possibly completing.
Leaving async out of this to start with...
With the break, the end of the lambda expression is reachable, therefore the return type of the lambda has to be void.
Without the break, the end of the lambda expression is unreachable, so any return type would be valid. For example, this is fine:
Func<string> foo = () => { while(true); };
whereas this isn't:
Func<string> foo = () => { while(true) { break; } };
So without the break, the lambda expression would be convertible to any delegate type with a single parameter. With the break, the lambda expression is only convertible to a delegate type with a single parameter and a return type of void.
Add the async part and void becomes void or Task, vs void, Task or Task<T> for any T where previously you could have any return type. For example:
// Valid
Func<Task<string>> foo = async () => { while(true); };
// Invalid (it doesn't actually return a string)
Func<Task<string>> foo = async () => { while(true) { break; } };
// Valid
Func<Task> foo = async () => { while(true) { break; } };
// Valid
Action foo = async () => { while(true) { break; } };
Related
I have a my method X that invokes method Y that I want to be passed as a parameter.
The challenge is the Y can virtually be any method, but in my specific case it can be an Action, Func<bool> or Func<int?>. Here's receiving end:
void X(Delegate y) {
if (y is Action action) { /* ... */ }
else if (y is Func<bool> boolFunction) { /* ... */ }
else if (y if Func<int?> intFunction) { /* ... */ }
else throw new NotImplementedException();
// do the other stuff depending on `y`
}
Using this as:
X(Y);
doesn't compile and shows:
Error CS1503 Argument 1: cannot convert from 'method group' to 'Delegate'
However, invoking like this:
X(new Action(() => Y()));
works! My problem with this is it looks ugly, involves "useless" boilerplate code, using lambdas to just call method, instead passing method as delegate.
Of course it is solvable by creating 3 different method signatures, accepting Action, Func<bool> and Func<int?> as delegate argument, but again - BOILERPLATE code, repeating code - all the things I want to avoid here.
So what is the succinct an elegant way to solve this in C#?
EDIT: To clarify the question - this is a "code golf" type of a question. There are many, many ways to do what I intend to do, they all work, and I have even a great choice in fast and slow solutions, because in my specific case the performance is not important (it handles user click, and all Reflection calls in the world are way faster than users's mice). I asked the question to improve my advanced C# skills guessing there are some syntax flavors more elegant and matched to the particular challenge. That's the way I learned C# from scratch. You can use callbacks if you don't know "async / await" syntax, you can use loops if you don't know LINQ. You can pass boxed objects if you don't know how to use generics. If there is a specialized language feature to express the idea in a better way - I want to learn it.
The error occurs because you are passing in Y, which could refer to any overload with the name Y. This could be returning an int, passing in a string etc. The compiler doesn't know which overload to use, so it's giving you that error. You just need to tell it what delegate type it is:
X(new Action<int>(Y));
X((Action<int>)Y);
This will require a slight modification to your code, but X<Action<int>>(Y)
(Change your definition of X to
private void X<TDelegate>(TDelegate del) where TDelegate : Delegate
{
if (del is Action action) { /* ... */ }
else if (del is Func<bool> boolFunction) { /* ... */ }
else if (del is Func<int?> intFunction) { /* ... */ }
else throw new NotImplementedException();
// do the other stuff depending on `y`
}
ReSharper actually suggested to convert it to a switch:
private void X<TDelegate>(TDelegate del) where TDelegate : Delegate
{
switch (del)
{
case Action action: /* ... */
break;
case Func<bool> boolFunction: /* ... */
break;
case Func<int?> intFunction: /* ... */
break;
default:
throw new NotImplementedException();
}
// do the other stuff depending on `y`
}
P.S. I believe generic is the most efficient, and X(new Action(()=> Y())) is needlessly verbose and makes the compiler introduce extra functions. If you have to use it, simplify it to X(new Action(Y))
A solution with one overload method :
class Program
{
static void Main(string[] args)
{
InvokeMethod(MethodVoid);
InvokeMethod(MethodBool);
InvokeMethod(MethodInt);
}
public static void InvokeMethod(Action x)
{
x.Invoke();
}
public static void InvokeMethod<T>(Func<T> x)
{
InvokeMethod(() => x());
}
public static void MethodVoid()
{
}
public static bool MethodBool()
{
return true;
}
public static int? MethodInt()
{
return 42;
}
}
Recently I realized that I can make actually anything awaitable if I implement a GetAwaiter extension method for the type. I know it is completely nonsense but I started to play with that just for fun:
// a minimal awaiter to make the compiler happy
public class MyAwaiter<T> : INotifyCompletion
{
public bool IsCompleted { get; } = true
public T GetResult() => default(T);
public void OnCompleted(Action continuation) { }
}
And the required extension method:
public static class Extensions
{
// await them all!
public static MyAwaiter<T> GetAwaiter<T>(this T obj)
{
return new MyAwaiter<T>();
}
}
Now I can commit this black magic:
private async Task Magic()
{
await "haha!";
await 42;
// await new object(); // <- this line does not compile
}
Awaiting an object fails:
ConfiguredTaskAwaitable<object> does not contain a definition for IsCompleted
I do not understand how ConfiguredTaskAwaitable<object> comes in when I return a MyAwaiter<T> instance. But never mind, second try:
public static MyAwaiter<object> GetAwaiter(this object obj)
{
return new MyAwaiter<object>();
}
Now none of the awaits work:
The call is ambiguous between the following methods or properties: Test.Extensions.GetAwaiter(object) and Test.Extensions.GetAwaiter(object)
This is even more confusing message than the previous one.
If I change the type in the signature to string or int, then I can await strings and integers respectively; however, object does not work. Has someone any clue what in the background happens in case of object?
The only problem I can see is a missing semicolon:
public bool IsCompleted { get; } = true
Your code before your second try (the first 3 pieces of code) including await new object(); compiles on my machine, just like expected. I tried both .NET CORE and .NET framework 4.6 console applications in VS 2017 Community v15.2(26430.6).
Check your code and compiler version again.
I want to make a function to run stuff in a throw-away thread... aka keep executing stuff without waiting for the function in the line before it to excute.
So i made a little function here...
public static object Do(System.Action Method)
{
object ret;
System.Threading.Thread t = new System.Threading.Thread(() =>
{ret = Method(); });
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
return ret;
}
Looks simple... there is only one problem... i get the following errors
Cannot implicitly convert type 'void' to 'object'
Use of unassigned local variable 'ret'
I don't care about the second because it will fix itself if i just fix the first... but i don't seem to find a solution for the first...
In short:
All i want is to get the return value of the function chosen aka...
I want the following code to work:
string TEST = Do(() => Console.ReadKey()).ToString();
But the method itself is broken.
Action delegate does not return a value.
Use Func<object> to return object from a passed function.
Also in this case the variable will be most likely returned before the function completes.
I recommend using async/await combination instead. In order for your construction to work you would have do something like this:
public static async Task<object> Do(Func<object> Method)
{
object ret = null;
await Task.Run(
() =>
{
ret = Method();
});
return ret;
}
Which boils down to:
public static async Task<object> Do(Func<object> Method)
{
return Task.Run(Method);
}
Example code:
class Program
{
static AutoResetEvent MyThreadCompletedEvent = new AutoResetEvent(false);
static async void MyThread()
{
Console.WriteLine((await MyClass<ConsoleKeyInfo>.Do(Console.ReadKey)).ToString());
MyThreadCompletedEvent.Set();
}
static void Main(string[] args)
{
Task.Run(() => MyThread());
// Do stuff
// Ensure to wait for MyThread to complete
MyThreadCompletedEvent.WaitOne();
}
}
public static class MyClass<T>
{
public static async Task<object> Do(Func<T> Method)
{
return await Task.Run(Method);
}
}
Instead of creating new thread you could do:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(MyClass<ConsoleKeyInfo>.Do(Console.ReadKey));
}
}
public static class MyClass<T>
{
public static object Do(Func<T> Method)
{
return Method();
}
}
From your title:
How do i get return value of action running in a thread in C#?
You can't. If the thread is still running, the "return value" has not yet been computed. It is not available to return, even if you used the correct Func<T> instead of Action<T>.
In other words, the laws of physics in our universe as we currently know them do not allow for retrieving information from the future.
I want the following code to work:
string TEST = Do(() => Console.ReadKey()).ToString();
Assuming you meant TEST to have the value of the pressed key, then you have to wait for the key to be pressed. The same thing would be obtained with:
string TEST = Console.ReadKey().ToString();
(though you probably would want to use the .KeyChar property...)
Since I can define an Action as
Action a = async () => { };
Can I somehow determine (at run time) whether the action a is async or not?
No - at least not sensibly. async is just a source code annotation to tell the C# compiler that you really want an asynchronous function/anonymous function.
You could fetch the MethodInfo for the delegate and check whether it has an appropriate attribute applied to it. I personally wouldn't though - the need to know is a design smell. In particular, consider what would happen if you refactored most of the code out of the lambda expression into another method, then used:
Action a = () => CallMethodAsync();
At that point you don't have an async lambda, but the semantics would be the same. Why would you want any code using the delegate to behave differently?
EDIT: This code appears to work, but I would strongly recommend against it:
using System;
using System.Runtime.CompilerServices;
class Test
{
static void Main()
{
Console.WriteLine(IsThisAsync(() => {})); // False
Console.WriteLine(IsThisAsync(async () => {})); // True
}
static bool IsThisAsync(Action action)
{
return action.Method.IsDefined(typeof(AsyncStateMachineAttribute),
false);
}
}
Of course, You can do that.
private static bool IsAsyncAppliedToDelegate(Delegate d)
{
return d.Method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null;
}
If you're looking to build some logic, based on whether a sync or async lanbda has been passed to your method - just introduce overloads.
public void MyMethod(Action action)
{
DoStuff();
}
public void MyMethod(Func<Task> asyncAction)
{
DoOtherStuff();
}
Consider:
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
C c = new C();
c.FooAsync(); // warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
((I)c).FooAsync(); // No warning
}
}
class C : I
{
public async Task FooAsync()
{
}
}
interface I
{
Task FooAsync();
}
If I call the async method directly on the c object, I get a compiler warning. There's potentially a bug here, so I'm glad for the warning.
However, if I make the same call on an interface method, I get no warning. It would be easy to let a bug slip past in this code.
How can I ensure that I don't make this mistake? Is there a pattern I can apply to protect myself?
Main is not async, so it can't use await. This seems to confuse the compiler messages slightly. If you put the calls into an actual async method;
static void Main(string[] args)
{
Task.Run(async () =>
{
C c = new C();
c.FooAsync();
((I) c).FooAsync();
});
}
...both will warn.
Line 10: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Line 11: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
EDIT: It seems like all methods that return Task inside async methods will warn unless you await or assign them; note that we're working with the interface that doesn't even mention async;
interface I
{
Task FooAsync();
}
static void Main(string[] args)
{
I i = null;
i.FooAsync(); // Does not warn
// await i.FooAsync(); // Can't await in a non async method
var t1 = i.FooAsync(); // Does not warn
Task.Run(async () =>
{
i.FooAsync(); // Warns CS4014
await i.FooAsync(); // Does not warn
var t2 = i.FooAsync(); // Does not warn
});
}
The logic for this warning seems to be:
in an async method, warn whenever a Task-returning method is called, but the result is ignored
in a normal (non-async) method, warn whenever a Task-returning async method is called, but the result is ignored
For example, look at this (nonsensical) code:
Task NonAsyncMethod()
{
AsyncMethod(); // warnig
NonAsyncMethod(); // no warning
return null; // to make the code compile
}
async Task AsyncMethod()
{
AsyncMethod(); // warning
NonAsyncMethod(); // warning
}
This is why you're not getting the warning with the interface: the interface method isn't (and can't) be marked as async.
I think the reason for this is that in old, pre-async code, it's common to for example call task.ContinueWith() and ignore its result. If the warning was reported in this case too, relatively large amount of old correct code would suddenly become warnings.
A warning should be output when there is a large likelihood of a bug. I think that the cases that are reported are much more likely to be bugs than the case which isn't. So to me, this behavior make sense.
If you want to make sure you don't make this mistake, be careful about calling Task-returning methods from non-async code.
I would venture to say that it is impossible to make this warning on compilation level. to support my point, look at this example:
interface I
{
Task Foo();
}
class A : I
{
public Task Foo()
{
}
}
class B : I
{
public async Task Foo()
{
}
}
public class Program
{
private static void Main(string[] args)
{
I i;
if (Console.ReadLine() == "1")
{
i = new A();
}
else i = new B();
i.Foo();
}
}
Your first thought might be: But this is an absurd situation. But some design patterns (an example is the factory method) using mechanisms instantiate derived classes from a very dynamic way.
So how the VS can know if the method is async or not?
I guess you may be asking for too much here.
interface I
{
void Foo();
}
class C {} // does not implement I
class Program
{
static void Main(string[] args)
{
C c = new C();
((I)c).Foo(); // Generates no compiler warning
}
}
Nevertheless, casting happens at runtime and there is nothing such as async at runtime (or in CIL). Compiler converts async Task Foo() into Task Foo() implemented as a state-machine of co-routines.
The Lindhart.Analyser.MissingAwaitWarning NuGet package checks this for you. Install the nuget package in your projects and you'll get a compiler warning when a method returns a Task that is not awaited.
more info