I have an interface like this
public interface IServerDataProvider
{
string Val1 { get; }
string Val2 { get; }
event EventHandler<EventArgs> Val1Changed;
event EventHandler<EventArgs> Val2Changed;
}
It gives the user access to two strings retrieved from a server and events that are triggered when these strings change.
Learning about async-await in c#, I can make a fairly simple implementation that periodically checks if these values are changed on a server :
public class ServerDataProviderAsync : IServerDataProvider
{
public event EventHandler<EventArgs> Val1Changed;
public event EventHandler<EventArgs> Val2Changed;
private string _val1Url = "someUrl";
private string _val2Url = "otherUrl";
private const int _delayMs = 1000;
public ServerDataProviderAsync()
{
Start();
}
private async void Start()
{
Val1 = await DownloadString(_val1Url);
Val2 = await DownloadString(_val2Url);
Val1UpdateLoop();
Val2UpdateLoop();
}
private async void Val1UpdateLoop()
{
await Task.Delay(_delayMs);
Val1 = await DownloadString(_val2Url);
Val1UpdateLoop();
}
private async void Val2UpdateLoop()
{
await Task.Delay(_delayMs);
Val2 = await DownloadString(_val1Url);
Val2UpdateLoop();
}
private string _val1;
public string Val1
{
get { return _val1; }
private set
{
if (_val1 != value && value != null)
{
_val1 = value;
OnContentChanged(Val1Changed);
}
}
}
private string _val2;
public string Val2
{
//similar to Val1
}
private async Task<string> DownloadString(string url)
{
using (var wb = new WebClient())
{
try { return await wb.DownloadStringTaskAsync(url); }
catch { /*log error*/}
}
return null;
}
private void OnContentChanged(EventHandler<EventArgs> handler)
{
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
And it can be used something like this from MainWindow :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var dataProvider = new ServerDataProviderAsync();
//hook up to events and display strings in GUI
}
}
Now my question is if this is a good implementaion? Is there a better way?
The first part I'm worried about are the async void methods. I've read they should only be used for event handlers. Are they bad in this case? And if so, why?
The other thing I'm worried about is the recursive way the update loops work. But it seems that since it always awaits tasks that are not already finished, it will not keep adding to the call stack.
You should really use an [iterative] infinite loop to create an infinite loop rather than using infinite recursion.
Using recursion means constantly spending the effort to re-create the exact same state machine from scratch each iteration instead of using the perfectly fine state machine that you already have, and it needlessly obfuscates the code and reduces clarity (to the point that you yourself weren't even sure of the possible negative repercussions; you don't want every single other person who reads the code to have to think through the same problem) for no real gain. Additionally, if you want to be able to propagate exceptions generated in this method to the caller (discussed further below) then using recursion has a number of problems, such as completely messing up the call stack, making actually throwing the exception through all of those levels difficult, and also creating a memory leak in that each "finished" state machine wouldn't be able to be cleaned up.
As for the methods being void, that's not particularly problematic. The reason that one would normally want a Task returned is so that you can tell when the operation finishes. Your operations never finish, they run forever. Getting a task that will never be completed isn't really any more or less useful than not getting a task at all in most circumstances.
The only way it might be relevant is error handling. If your loop generates an error and the method is void it needs to be responsible for handling that error itself, because it is conceptually a top level method. If it returns a Task then it gets the luxury of simply throwing that exception to its caller and leaving that caller responsible for handling that Exception. This would be the only reason to not return void for a method that is supposed to run forever.
Related
I am currently building out a custom task manager and I'm wondering if it's possible to tell the task manager to listen for a specific event (OnSomething below), and then invoke a callback method when the task raises that event. However, mentally I can't see how it's possible to listen for an event that doesn't exist at the base class level. For example, I have a base class that contains basic information about the task called CustomTask:
public abstract class CustomTask {
public bool IsRunning { get; private set; } = false;
public void Start() {
IsRunning = true;
DoSomething();
IsRunning = false;
}
protected abstract void DoSomething();
}
For the sake of SO readers, I've simplified the definition, but you get the gist of it. It contains basic details, a few methods for starting and canceling, provides basic state management (simplified IsRunning here), etc.
I then have custom tasks that derive from CustomTask, in this case, let's focus on a sample task called CustomTaskA. It contains a definition for an event called OnSomething, which someone, somewhere may want to listen for:
public sealed class CustomTaskA : CustomTask {
protected override void DoSomething() => RaiseOnSomething(this, new EventArgs());
public event EventHandler<EventArgs> OnSomething;
private void RaiseOnSomething(object sender, EventArgs e) => OnSomething?.Invoke(sender, e);
}
Now, the CustomTaskManager registers tasks, tracks them via Guid, manages them and more, but for simplicity:
public sealed class CustomTaskManager {
// Singleton setup.
private static CustomTaskManager _instance = new CustomTaskManager();
public static CustomTaskManager Instance {
get {
// Simplified for SO.
if (_instance == null)
_instance = new CustomTaskManager();
return;
}
}
// Collection of tasks.
private Dictionary<Guid, CustomTask> _tasks = new Dictionary<Guid, CustomTask>();
// Register and start a task.
public bool TryRegisterAndStartTask(CustomTask task, out Guid taskId) {
taskId = Guid.Empty;
try {
// Register task.
taskId = Guid.NewGuid();
_tasks.Add(taskId, task);
// Listen for events.
// Start task.
task.Start();
} catch (Exception e) {
// Log exception.
}
return false;
}
}
When registering and starting a task, I'd like to tell the task manager I want to listen for OnSomething, and if OnSomething is invoked, I want the task manager to call a method OnSomethingWasRaised. For example:
TaskManager.Instance.TryRegisterAndStartTask(task, out Guid taskId, task.OnSomething, OnSomethingWasRaised);
private static void OnSomethingWasRaised(object sender, EventArgs e) {
Console.WriteLine("Woohoo!");
}
I know the specifying and invoking a callback method is entirely possible, and listening for events is plausible with reflection.
Is there a way (with or without using reflection) to listen for a specified event defined on a derived object and then invoke a specified callback method?
NOTE: Please excuse any syntactical errors as I hand-typed the snippets to keep them minimal.
Problem with (proposed) approach like this:
TryRegisterAndStartTask(task, out Guid taskId, task.OnSomething, OnSomethingWasRaised);
is that you cannot pass event as argument, or store it in variable, because event is just a set of two methods (add and remove), just like property is a set of two methods get and set.
You can of course change event to "raw" delegate:
public EventHandler<EventArgs> OnSomething;
This one you can pass by reference:
public bool TryRegisterAndStartTask(CustomTask task, ref EventHandler<EventArgs> del, EventHandler<EventArgs> sub, out Guid taskId) {
taskId = Guid.Empty;
// subscribe
del += sub;
...
}
CustomTaskManager.Instance.TryRegisterAndStartTask(task, ref task.OnSomething, OnSomethingWasRaised, out var taskId);
But that's usually not a good idea, since you are losing private scope of events - with events one can only add\remove delegates, with raw delegate anyone can do anything, like invoking or setting to null.
If regular event stays - that means reflection is the only way to achieve your goal, and even worse - you'll have to reference to the event you want to subscribe to by string name, not by an actual reference, though you can use nameof(task.OnSomething). Then, you are losing compile time validation of subscription delegate type. Say you want to subscribe to event Action Something but passing Func<string> delegate there. It will compile fine with reflection approach, and fail only at runtime.
Still if you insist that will look something like this:
public bool TryRegisterAndStartTask(CustomTask task, string eventName, Delegate sub, out Guid taskId) {
taskId = Guid.Empty;
// subscribe
var ev = task.GetType().GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance);
var addMethod = ev.GetAddMethod(); // this can be null or private by the way
addMethod.Invoke(task, new [] {sub});
...
}
And called like this:
var task = new CustomTaskA();
EventHandler<EventArgs> handler = OnSomethingWasRaised;
CustomTaskManager.Instance.TryRegisterAndStartTask(task, nameof(task.OnSomething), handler, out var taskId);
Ugly, unsafe, and not worth it in your scenario, in my opinion.
I have a class with properties that are bound to my view. To keep my view up-to-date, I implement INotifyPropertyChanged and raise the event everytime some property changes.
Now I got some heavy functions that freeze my application. I want to put them into a background task.
First: here my current approach
(e.g. on button click)
private async void HeavyFunc()
{
foreach (var stuff)
{
count += await Task.Run(() => stuff.Fetch());
}
if (count == 0)
//...
}
stuff class
public async Task<int> Fetch()
{
//network stuff
RaisePropertyChanged("MyProperty");
}
public async void RaisePropertyChanged(string pChangedProperty)
{
await Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new ThreadStart(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty);
}
);
}
The code above gives an exception ("DependencySource" must be created in the same thread like "DependencyObject").
AFAIK, you generally need to create a new thread and run it (while awaiting it). ´await Task.Run(...);´ should do this job.
Since the PropertyChanged event directly influences the UI, calling it in the UI thread seems to be a good decision. This is why I call Dispatcher.BeginInvoke.
What I don't understand: the exception above is caused when different threads are responsible for the data. But I explicitely calling the event on my UI-thread and the object should be created by the UI-thread too. So why do I get an exception?
My main question is: How do I implement the events for the INotifyPropertyChanged interface generally to avoid or handle most of the async programming problems like above? What should be considered while constructing the functions?
Now I got some heavy functions that freeze my application.
If you're really doing asynchronous "network stuff", then it shouldn't be freezing the app.
My main question is: How do I implement the events for the INotifyPropertyChanged interface generally to avoid or handle most of the async programming problems like above?
The approach that I prefer is to not handle this in the event raising code. Instead, structure the rest of your code so that it respects the UI layer.
In other words, divide your "service" (or "business logic") code from your "UI" code so that it works like this:
// In StuffService class:
public async Task<Result> FetchAsync()
{
//network stuff
return result;
}
// In StuffViewModel class:
public async void ButtonClicked()
{
foreach (var stuff)
{
var result = await Task.Run(() => _stuffService.FetchAsync());
MyProperty = result.MyProperty;
count += result.Count;
}
if (count == 0)
//...
}
public Property MyProperty
{
get { return _myProperty; }
set
{
_myProperty = value;
RaisePropertyChanged();
}
}
private void RaisePropertyChanged([CallerMemberName] string pChangedProperty = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty));
}
This way, there's no manual thread jumping, all properties have the standard ViewModel implementation, the code is simpler and more maintainable, etc.
I did leave in the call to Task.Run, although this should be superfluous if your network calls are truly asynchronous.
My application uses scripts. So far, I've used C# for the scripts and compiled them using the CodeDomProvider. However, I've been thinking about switching to Lua using the NLua fork (a fork of the LuaInterface) because it's much easier to write scripts with plus I'm familiar with the syntax.
However, I'm facing a problem. Currently, I have an asynchronous method that returns a Task<bool>. It uses a TaskCompletionSource object and returns it's Result. That way, I can halt the execution of the script because it waits until the Result of the TaskCompletionSource object has been set, and only then returns this Result.
Now, with Lua - it's different. I obviously can't use the awaitoperator because it's a syntax of C# 5.0, and you can't use that in Lua. So that's why I'm asking if there's a workaround for this. I want to be able to achieve the same result as my old code (which is posted beneath this post) without having to use the awaitoperator. I've been told that I can do that with Task.ContinueWith, but I'm unfamiliar with this and the examples online are dull. If anyone can show me an example with my code, it'd be great.
Here's my method:
public async Task<bool> ReturnResult()
{
this.Response = new TaskCompletionSource<bool>();
return await this.Response.Task;
}
Here's the way I'm using it in my scripts:
var result = await ReturnResult();
The Result of the TaskCompletionSource object is set by another part of my code.
Basically, if you still failed to understand what I want to achieve - a method that halts it's execution until a response has been set by another part of the code. However, it has to be asynchronous, because I don't want my main thread to get stuck.
EDIT: Tried JonSkeet's suggestion and the code just runs without halting. Here's the full Script class.
public class Script
{
private Lua Lua { get; set; }
private TaskCompletionSource<bool> Response { get; set; }
public Script()
{
this.Lua = new Lua();
}
public void Run()
{
this.Lua.RegisterFunction("log", this, typeof(Script).GetMethod("Log"));
this.Lua.RegisterFunction("returnResult", this, typeof(Script).GetMethod("ReturnResult"));
this.Lua.DoFile(#"C:\test.lua");
}
public void SetResponse(bool response)
{
this.Response.SetResult(response);
}
public Task<bool> ReturnResult()
{
this.Response = new TaskCompletionSource<bool>();
return this.Response.Task;
}
public void Log(string text)
{
MessageBox.Show(text);
}
}
Here's the code of Form1:
public partial class Form1 : Form
{
private Script Script { get; set; }
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Script = new Script();
this.Script.Run();
}
private void button2_Click(object sender, EventArgs e)
{
this.Script.SetResponse(true);
}
}
Just throw two buttons and use the first one to run, second one to set response.
The Lua script is:
result = returnResult()
log("returned " .. result)
Download NLua from here.
Okay, as you now claim this has nothing to do with Lua, here's how you would call the method in C#, then log only when the task had completed:
Task<bool> task = ReturnResult();
task.ContinueWith(t => Log("Returned " + t.Result));
This does not halt execution at all - it just says that when the task returned from ReturnResult completes, it should call the logging code.
For production code, you would probably want to check whether the task was faulted, etc. There are overloads of ContinueWith which allow you to specify under which circumstances you want to run the continuation (only on success, only on fault etc), and you can add multiple continuations. But to get you going, the above is probably good enough.
I have an object that takes a long time to be initialized. Therefore I the capability to Start Initializing on application startup. Any subsequent calls to methods on the class we need to have a delay mechanism that waits for the class to finish initialization.
I have a couple of potential solutions however I am not entirely satisfied with either of them. The first uses Task.Delay in a while loop and the second uses SemaphoreSlim but involves some unnecessary blocking. I feel this must be a fairly common requirement, can anybody provide some advice on how to best manage this?
Oh btw, this is a Metro application so we have limited API's
Here is the pseudocode:
public class ExposeSomeInterestingItems
{
private InitialisationState _initialised;
private readonly SemaphoreSlim _waiter =
new SemaphoreSlim(0);
public async Task StartInitialize()
{
if (_initialised == InitialisationState.Initialised)
{
throw new InvalidOperationException(
"Attempted to initialise ActiveTrackDown" +
"loads when it is already initialized");
}
_initialised =
InitialisationState.StartedInitialisation;
new TaskFactory().StartNew(async () =>
{
// This takes some time to load
this._interestingItems =
InterestingItemsLoader.LoadItems();
_waiter.Release();
_initialised = InitialisationState.Initialised;
});
}
public InterestingItem GetItem(string id)
{
DelayUntilLoaded();
DelayUntilLoadedAlternative();
}
private async Task DelayUntilLoaded()
{
if (_initialised == InitialisationState.NotInitialised)
{
throw new InvalidOperationException("Error " +
"occurred attempting to access details on " +
"ActiveTrackDownloads before calling initialise");
}
while (true)
{
if (_initialised == InitialisationState.Initialised)
{
return;
}
await Task.Delay(300);
}
}
private async Task DelayUntilLoadedAlternative()
{
if (_initialised == InitialisationState.NotInitialised)
{
throw new InvalidOperationException(
"Error occurred attempting to access details " +
"on ActiveTrackDownloads before calling initialise");
}
try
{
await _waiter.WaitAsync();
}
finally
{
_waiter.Release();
}
}
}
I think that a better design would be an asynchronous factory, where the calling code awaits the object creation and then receives a regular object instance.
Stealing liberally from Stephen Toub:
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory) :
base(() => Task.Run(valueFactory)) { }
public AsyncLazy(Func<Task<T>> taskFactory) :
base(() => Task.Run(taskFactory)) { }
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
}
public static class ExposeSomeInterestingItemsFactory
{
public static AsyncLazy<ExposeSomeInterestingItems> Instance
{
get { return _instance; }
}
private static readonly AsyncLazy<ExposeSomeInterestingItems> _instance =
new AsyncLazy<ExposeSomeInterestingItems>(() => new ExposeSomeInterestingItems());
public static void StartInitialization()
{
var unused = Instance.Value;
}
}
public class ExposeSomeInterestingItems
{
public ExposeSomeInterestingItems()
{
// This takes some time to load
this._interestingItems = InterestingItemsLoader.LoadItems();
}
public InterestingItem GetItem(string id)
{
// Regular logic. No "delays".
}
}
...
var exposeSomeInterestingItems = await ExposeSomeInterestingItemsFactory.Instance;
var item = exposeSomeInterestingItems.GetItem("id");
That way, you keep the Single Responsibility Principle nicely:
AsyncLazy<T> combines Task<T> with Lazy<T> (so the instance is created asynchronously only when needed).
ExposeSomeInterestingItemsFactory contains construction logic.
ExposeSomeInterestingItems is only concerned with exposing interesting items, rather than having to pollute all its members with asynchronous delays.
Also, this solution is asynchronous throughout (no blocking), which is good (particularly for Metro apps).
Update, 2012-09-14: I've taken this code and cleaned it up and commented it on my blog.
You can use the Task<T> for this. This will take care of all the synchronisation for you and allows you to block untill the value is available:
private static Task<HeavyObject> heavyObjectInitializer;
// Call this method during application initialization
public static void Bootstrap()
{
heavyObjectInitializer = new Task<HeavyObject>(() =>
{
// creation of heavy object here
return new HeavyObject();
});
// Start running the initialization right now on a
// background thread. We don't have to wait on this.
heavyObjectInitializer.Start();
}
// Call this method whenever you need to use the object.
public static HeavyObject GetHeavyObject()
{
// Get the initialized object, or block untill this
// instance gets available.
return heavyObjectInitializer.Result;
}
Optionally, you can also query to see if the object is available or not:
public static bool IsHeavyObjectAvailable
{
get { return heavyObjectInitializer.IsCompleted; }
}
Put the method calls into a queue which you process when you finish initialising. Only put methods into the queue when you have not yet initialised.
You could move to a an event driven architecture where you application is in different states.
Initially the application moves into the Starting state. In this state HeavyObject is created using a background task. When the initialization is complete an event is fired. (You don't have to use an actual .NET event. You can use callbacks or something similar and frameworks like Reactive Extensions allows you to compose sequences of events.)
When all initialization events have fired you move into the Started state of your application. For an UI application this could modify the UI to enable some previously disabled operations.
Check this Prototype Pattern. Maybe it can help you
You only need to create your object once and clone it when you need another one.
I'd like to hear opinions on the best way to handle asynchronous operations with the Command pattern. Say we have the following example:
public class MyCommand
{
// Sets up receiver and does whatever stuff
public void Execute()
{
_myReceiver.DoSomething();
}
}
The problem is: MyCommand doesn't know whether MyReceiver.DoSomething() has async portions of code. If i wanted to push MyCommand into an undo stack after its execution, i couldn't guarantee that its receiver action has been fully executed, making it uncertain to know if MyCommand reached a state where undoing is possible or not.
I personally thought on the following solution:
Implement some sort of state control in Command
Include "BeginExecute" and "EndExecute" in Command
Include events in MyReceiver and make Command subscribe to them (that seems smelly to me)
To wrap things up, MyCommand would turn into:
public class MyCommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => this.EndExecute();
}
public void BeginExecute()
{
this.EnterExecutionState();
_myReceiver.DoSomething();
}
public void EndExecute()
{
this.LeaveExecutionState();
}
// State handling related stuff
}
I now have the means to make sure the Command's receiver has finished executing whatever action and it's ready to be pushed into the undo stack. However, to event-spam every single Receiver class that contains async operations really bugs me.
I haven't found much about this topic in the Internet and would love to hear different approaches.
OBS: Make the Command manage all the asynchronous-related code isn't an option :).
I think you've got way too much going on in a single class. I would break it down like this:
// An immutable command, to be handled in-process.
// ICommand is a marker interface with no members.
public class DoSomething : ICommand
{
public readonly Id;
public DoSomething(Guid id)
{
Id = id;
}
}
// To be handled out-of-process.
[AsynchronousCommand]
public class DoSomethingThatTakesAReallyLongTime : ICommand
{
public readonly Id;
public DoSomethingThatTakesAReallyLongTime(Guid id)
{
Id = id;
}
}
// This guy could take any number of dependencies: ISomethingRepository, DbContext, etc.
// Doesn't matter, but it's probably gonna have dependencies.
public class DoSomethingHandler : IHandler<DoSomething>
{
public void Handle(DoSomething command) // IHandler<T>'s only member
{
// CRUD or call call a domain method
}
}
public class CommandService : ICommandService
{
public void Execute(params ICommand[] commands) // ICommandService's only member
{
foreach(var command in commands)
{
var handler = GetHandler(command); // Could use your IOC container.
if (HasAsyncAttribute())
new Action(() => handler.Handle(command)).BeginInvoke(null, null);
else
handler.Handle(command);
}
}
}
// Something that might consume these
public class SomethingController
{
private readonly ICommandService _commandService;
public SomethingController(ICommandService commandService)
{
_commandService = commandService;
}
[HttpPost]
public void DoSomething(Guid id)
{
_commandService.Execute(new DoSomething(id));
}
[HttpPost]
public void DoSomethingThatTakesAReallyLongTime(Guid id)
{
_commandService.Execute(new DoSomethingThatTakesAReallyLongTime(id));
}
}
The big advantage here is that you can distribute your commands to clients without explicitly dragging along all the dependencies that go with the handlers. The handlers should not be known to the client. All the client needs to know is that it sent a command, and all commands should be assumed to succeed.
Something like this?
public interface ICommand
{
void Execute();
event EventHandler Finished;
}
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => Finished(); // dont forget null check here.
}
public void Execute()
{
_myReceiver.DoSomething();
}
public event EventHandler Finished;
}
This way, user of this command can register to Finished event so it knows when command has finished its async behaviour and can act acordingly.
Or if you dont wan't to use event, then what about callback?
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
}
public void Execute()
{
_myReceiver.DoSomething(() => Finished()); // dont forget null check here.
}
public event EventHandler Finished;
}
Either way, there simply need to be a way for MyReciever to notify its caller, that it finished. There is no way to bypass it.
First I would add to the name of the method Async to esplicitly signal to your Command class consumer that method executes in async way.
Second, I would add like parameter an Action<T> which will be called as method async call completes. So this method caller can be notified when async sction was terminated.
Edit
obj.DoSomethingAsync(... params, Action<T> onComplete)
If you are going to impose the requirement that all processing is completed before control returns to your Execute method, without modifying the calling code's behavior, you could modify the way that your actions execute.
First initialize all your asynchronous calls and block(wait) on the current thread for calls to return. I'm not sure what the nature of your asynchronous calls are, as in if they are in a Thread that you are aware of, or will be returned on an arbitrary thread, but you should be able to come up with some kind of thread synchronization for your problem.
Try using a Semaphore to block current thread(after calling your async methods), and release the semaphore when all your async methods have returned their response(s). This will have the effect of "re-synchronizing" your async calls.
You can use another synchronization method, but a Semaphore is simple enough to understand.