Cancellation async in IDisposable class - c#

In my project I use a manager to control a plugin. The main idea is that this plugin must work only in single thread in multythreads WPF application. There is only one instance of plugin in PluginController.
So when I call Start method: it stops plugin (if running) and start it with new argument. Few times a second plugin notificate caller about it's state, and ViewModel shows it in the WPF window.
When I call method Start some times one after one, i see that the previous instance of ViewModel is not destroyed, but only sleeps after Stop. And it calls Update method as god as a new one instance. So my interface twiches becouse two instances are updating it's state. In log is see alternately lines from first one and second one.
But when I call Start(...) then Stop() and then Start(...) again everything works fine.
So
SomeManager.Start(...);
SomeManager.Start(...);
works with errors. And
SomeManager.Start(...);
SomeManager.Stop();
SomeManager.Start(...);
works fine. Can anybody explain me my mistake?
Down lied simplified code.
public static SomeManager
{
public static void Start(SomeArg arg)
{
Stop(); // forgotten code
var vm = GetMainPageVM();
vm.SomeVM = new SomeViewModel(arg);
vm.SomeVM.StartCommand.Execute(null);
}
public static void Stop()
{
var vm = GetMainPageVM();
if (vm.SomeVM != null)
{
vm.SomeVM.Stop();
vm.SomeVM.Dispose();
vm.SomeVM = null;
}
}
}
public sealed SomeViewModel : ViewModelBase, IDisposable
{
private readonly Guid _guid = Guid.NewGuid();
private IPlugin _plugin;
private SomeArg _arg;
public ICommand StartCommand {get; }
public CancellationTokenSource Source {get; }
public SomeViewModel(SomeArg arg)
{
this._arg = arg;
this._plugin = PluginController.GetPluginByName("SomePlugin");
StartCommand = new RelayCommand(StartAsync);
}
~SomeViewModel()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{ ... }
private async Task StartAsync()
{
var progress = new Progress<ISomeProgress>(Update);
try
{
await StartImplementationAsync(progress).ConfigureAwait(false);
}
catch (Exception e) { ... }
}
private async Task StartImplementationAsync(Progress<ISomeProgress> progress)
{
var result = await this._plugin.startAsync(
this._arg,
progress,
this.Source.Token
).ConfigureAwait(false);
}
public void Stop()
{
this._plugin.Stop();
}
private void Update() {log.Debug($"this._guid" ....); }
}
public sealed SomePlugin: IPlugin
{
public async Task<SomeResult> StartAsync(SomeArg args, IProgress<SomeProgress>, CancellationToken cancellationToken)
{ ... }
public void Stop() { ... }
}
UPDATE: I think the problem in simple words is : how to correctly cancel async operation in IDisposable object in normal case with CancellationTokenSource.Cancel() and in unnormal case when Dispose() or Finalizer is called

Related

Task start/stop handling using abstract classes

I have this code logic to handle my tasks:
public abstract class BaseJob{
public bool Running { get; private set; }
public CancellationToken Token => _tokenSource.Token;
private CancellationTokenSource _tokenSource;
public virtual void Start()
{
_tokenSource = new CancellationTokenSource();
Running = true;
}
}
now when I inherit BaseJob I will have this situation:
public class CustomJob: BaseJob{
public MyEnum Status {get; private set;}
public StopRequested { get; set;}
public override async void Start(){
base.Start();
while(!StopRequested){
await MyLongRunningMethod();
}
//base.Running = true but I can't access it here!
}
public async Task<bool> MyLongRunningMethod(){
await Task.Run(()=>{
//more work
},this.Token);
//someWork
return false;
}
}
As you can see I can't access Running to set it to false as soon as myJob finishes, and I want BaseJob to handle that.
What code logic changes must I bring to the base class in order to automatically detect when myJob finishes, and then finalize the task with Running = false without accessing the least from the inherited classes?
You could rewrite your abstract class to have an internal start method that can know when your job completes. Assuming your job is synchronous and takes no parameters:
public abstract class BotTask
{
private bool Running { get; set; }
public CancellationToken Token => _tokenSource.Token;
private CancellationTokenSource _tokenSource;
public abstract void Start();
protected void InternalStart(Action job)
{
_tokenSource = new CancellationTokenSource();
Running = true;
job();
Running = false;
}
}
public class CustomTask : BotTask
{
public override void Start()
{
InternalStart(MyJob);
}
}
Make Running set protected instead of private. This way it cant be accessed from outside but it can accessed by entities who inherit from BotTask

Count all subscriptions of a subject

I have a Subject where I subscribe methods that should be called when a determined event in a game happens.
public Subject<SomeEvent> TestSubject = new Subject<SomeEvent>();
Some instances subscribe to that Subject.
TestSubject.Subscribe(MyMethod);
My objective is to count how many methods have been subscribed to that Subject. I've seen some examples using Count() extension but I need an int as a return value so then I can use it somewhere else, and Count() returns an IObservable.
if (subjectCount > 0)
{
DoSomething();
}
Is there any way to get the number of subscriptions on a subject or do I need to keep track of them manually (having a public int SubjectSubcriptions and adding 1 everytime I subscribe a method) ?
Easiest way would be to create your own implementation of ISubject with a wrapper around a subject.
public class CountSubject<T> : ISubject<T>, IDisposable
{
private readonly ISubject<T> _baseSubject;
private int _counter;
private IDisposable _disposer = Disposable.Empty;
private bool _disposed;
public int Count
{
get { return _counter; }
}
public CountSubject()
: this(new Subject<T>())
{
// Need to clear up Subject we created
_disposer = (IDisposable) _baseSubject;
}
public CountSubject(ISubject<T> baseSubject)
{
_baseSubject = baseSubject;
}
public void OnCompleted()
{
_baseSubject.OnCompleted();
}
public void OnError(Exception error)
{
_baseSubject.OnError(error);
}
public void OnNext(T value)
{
_baseSubject.OnNext(value);
}
public IDisposable Subscribe(IObserver<T> observer)
{
Interlocked.Increment(ref _counter);
return new CompositeDisposable(Disposable.Create(() => Interlocked.Decrement(ref _counter)),
_baseSubject.Subscribe(observer));
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_disposer.Dispose();
}
_disposed = true;
}
}
}
I am curious if this is only for testing purposes or not. If so, then the Rx-Testing nuget package has the tools to give you this information.
e.g. you can validate the number of subscription in a unit test like this
TestScheduler scheduler = new TestScheduler();
var obs = scheduler.CreateColdObservable(
ReactiveTest.OnNext(1, "foo"),
ReactiveTest.OnNext(1000, "bar"),
);
//Do some work that should add subscriptions.
Assert.AreEqual(expectedSubriptionCount, obs.Subscriptions);

Cancelling a Task when an object is Finalized

I have a class which starts a Task and want to ensure that the Task stops when the object is garbage collected.
I have implemented the IDisposable pattern to ensure that if the object is disposed manually or used within a using block, then the Task stops correctly. However, I cant guarantee that the end user will call Dispose() or use the object within a using block. I know that the Garbage Collector will eventually call the Finalizer - does this mean that the task is left running?
public class MyClass : IDisposable
{
private readonly CancellationTokenSource feedCancellationTokenSource =
new CancellationTokenSource();
private readonly Task feedTask;
public MyClass()
{
feedTask = Task.Factory.StartNew(() =>
{
while (!feedCancellationTokenSource.IsCancellationRequested)
{
// do finite work
}
});
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
feedCancellationTokenSource.Cancel();
feedTask.Wait();
feedCancellationTokenSource.Dispose();
feedTask.Dispose();
}
}
~MyClass()
{
Dispose(false);
}
}
It was suggested in this question to add a volatile bool which is set from the Finalizer and observed from the task. Is this recommended, or is there a better way to achieve what I need?
(I'm using .NET 4 hence the use of TaskFactory.StartNew rather than Task.Run)
EDIT:
To give some context to the question - which is not actually shown in the above code snippet: I am creating a Network client class which has a mechanism to keep alive by regularly sending packets to the server. I chose not to put all this detail in the example as it wasn't relevant to my specific question. However, what I actually want is the ability for the user to set a KeepAlive boolean property to true, which will start a task to send data to the server every 60 seconds. If the user sets the property to false then the task stops. IDisposable got me 90% of the way there, however it relies on the user disposing it properly (explicitly or via using). I don't want to expose keep alive tasks to the user for them to cancel explicitly, I just want a "simple" KeepAlive = true/false to start/stop the task AND I want the task to stop when the user is finished with the object - even if they don't dispose of it properly. I'm starting to think that this isn't possible!
I'll sketch an answer. I'm not 100% confident that this will work. Finalization is a complicated issue and I'm not proficient in it.
There can be no object reference from the task to whatever object is supposed to be finalized.
You can't touch other objects from a finalizer that are not known to be safe. The built-in .NET classes do not usually document this safety property. You can't rely on that (usually).
class CancellationFlag { public volatile bool IsSet; }
You can now share an instance of this class between the task and MyClass. The task must poll the flag and MyClass must set it.
In order to ensure that the task never accidentally references the outer object I'd structure the code like this:
Task.Factory.StartNew(TaskProc, state); //no lambda
static void TaskProc(object state) { //static
}
This way you can explicitly thread any state through state. This would, at least, be an instance of CancellationFlag but under no circumstances a reference to MyClass.
I created the program below to explore the differences...
From my observations with it, it looks like it makes no difference whether it's a cancellation token or a volatile bool, what really matters is that the Task.StartNew method isn't called using a lambda expression.
Edit: to clarify: if the lambda refers to a static method, it's actually fine: the problem comes when the lambda causes a reference to the containing class to be included: so either a reference to a member variable of the parent class or else a reference to an instance method of the parent class.
Please do give this a try and let me know if you come to the same conclusion.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
Logger.LogFile = #"c:\temp\test\log.txt";
Task.Run(() =>
{
// two instances (not disposed properly)
// if left to run, this background task keeps running until the application exits
var c1 = new MyClassWithVolatileBoolCancellationFlag();
// if left to run, this background task cancels correctly
var c2 = new MyClassWithCancellationSourceAndNoLambda();
//
var c3 = new MyClassWithCancellationSourceAndUsingTaskDotRun();
//
var c4 = new MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference();
}).GetAwaiter().GetResult();
// instances no longer referenced at this point
Logger.Log("Press Enter to exit");
Console.ReadLine(); // press enter to allow the console app to exit normally: finalizer gets called on both instances
}
static class Logger
{
private static object LogLock = new object();
public static string LogFile;
public static void Log(string toLog)
{
try
{
lock (LogLock)
using (var f = File.AppendText(LogFile))
f.WriteLine(toLog);
Console.WriteLine(toLog);
}
catch (Exception ex)
{
Console.WriteLine("Logging Exception: " + ex.ToString());
}
}
}
// finalizer gets called eventually (unless parent process is terminated)
public class MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference : IDisposable
{
private CancellationTokenSource cts = new CancellationTokenSource();
private readonly Task feedTask;
public MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference()
{
Logger.Log("New MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference Instance");
var token = cts.Token; // NB: by extracting the struct here (instead of in the lambda in the next line), we avoid the parent reference (via the cts member variable)
feedTask = Task.Run(() => Background(token)); // token is a struct
}
private static void Background(CancellationToken token) // must be static or else a reference to the parent class is passed
{
int i = 0;
while (!token.IsCancellationRequested) // reference to cts means this class never gets finalized
{
Logger.Log("Background task for MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference running. " + i++);
Thread.Sleep(1000);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cts.Cancel();
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference Disposed");
}
else
{
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference Finalized");
}
}
~MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference()
{
Dispose(false);
}
}
// finalizer doesn't get called until the app is exiting: background process keeps running
public class MyClassWithCancellationSourceAndUsingTaskDotRun : IDisposable
{
private CancellationTokenSource cts = new CancellationTokenSource();
private readonly Task feedTask;
public MyClassWithCancellationSourceAndUsingTaskDotRun()
{
Logger.Log("New MyClassWithCancellationSourceAndUsingTaskDotRun Instance");
//feedTask = Task.Factory.StartNew(Background, cts.Token);
feedTask = Task.Run(() => Background());
}
private void Background()
{
int i = 0;
while (!cts.IsCancellationRequested) // reference to cts & not being static means this class never gets finalized
{
Logger.Log("Background task for MyClassWithCancellationSourceAndUsingTaskDotRun running. " + i++);
Thread.Sleep(1000);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cts.Cancel();
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRun Disposed");
}
else
{
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRun Finalized");
}
}
~MyClassWithCancellationSourceAndUsingTaskDotRun()
{
Dispose(false);
}
}
// finalizer gets called eventually (unless parent process is terminated)
public class MyClassWithCancellationSourceAndNoLambda : IDisposable
{
private CancellationTokenSource cts = new CancellationTokenSource();
private readonly Task feedTask;
public MyClassWithCancellationSourceAndNoLambda()
{
Logger.Log("New MyClassWithCancellationSourceAndNoLambda Instance");
feedTask = Task.Factory.StartNew(Background, cts.Token);
}
private static void Background(object state)
{
var cancelled = (CancellationToken)state;
if (cancelled != null)
{
int i = 0;
while (!cancelled.IsCancellationRequested)
{
Logger.Log("Background task for MyClassWithCancellationSourceAndNoLambda running. " + i++);
Thread.Sleep(1000);
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cts.Cancel();
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithCancellationSourceAndNoLambda Disposed");
}
else
{
Logger.Log("MyClassWithCancellationSourceAndNoLambda Finalized");
}
}
~MyClassWithCancellationSourceAndNoLambda()
{
Dispose(false);
}
}
// finalizer doesn't get called until the app is exiting: background process keeps running
public class MyClassWithVolatileBoolCancellationFlag : IDisposable
{
class CancellationFlag { public volatile bool IsSet; }
private CancellationFlag cf = new CancellationFlag();
private readonly Task feedTask;
public MyClassWithVolatileBoolCancellationFlag()
{
Logger.Log("New MyClassWithVolatileBoolCancellationFlag Instance");
feedTask = Task.Factory.StartNew(() =>
{
int i = 0;
while (!cf.IsSet)
{
Logger.Log("Background task for MyClassWithVolatileBoolCancellationFlag running. " + i++);
Thread.Sleep(1000);
}
});
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cf.IsSet = true;
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithVolatileBoolCancellationFlag Disposed");
}
else
{
Logger.Log("MyClassWithVolatileBoolCancellationFlag Finalized");
}
}
~MyClassWithVolatileBoolCancellationFlag()
{
Dispose(false);
}
}
}
}
Update:
Added a few more tests (now included above): and came to the same conclusion as "usr": the finalizer never gets called if there's a reference to the parent class (which makes sense: an active reference exists, therefore the GC doesn't kick in)

Unit testing a background thread with an interface

I have created a class, SenderClass, which will start and run a background worker from its constructor.
The method, RunWorker(), runs is a while(true) loop which will pop elements from a queue, send them through the method SendMessage(), and sleep for a small amount of time to allow new elements to be added to the queue.
Here lies the problem: How do I test the method that sends the element from the queue, without exposing it to those who uses the class?
Implementation:
public class SenderClass : ISenderClass
{
private Queue<int> _myQueue = new Queue<int>();
private Thread _worker;
public SenderClass()
{
//Create a background worker
_worker = new Thread(RunWorker) {IsBackground = true};
_worker.Start();
}
private void RunWorker() //This is the background worker's method
{
while (true) //Keep it running
{
lock (_myQueue) //No fiddling from other threads
{
while (_myQueue.Count != 0) //Pop elements if found
SendMessage(_myQueue.Dequeue()); //Send the element
}
Thread.Sleep(50); //Allow new elements to be inserted
}
}
private void SendMessage(int element)
{
//This is what we want to test
}
public void AddToQueue(int element)
{
Task.Run(() => //Async method will return at ones, not slowing the caller
{
lock (_myQueue) //Lock queue to insert into it
{
_myQueue.Enqueue(element);
}
});
}
}
Wanted interface:
public interface ISenderClass
{
void AddToQueue(int element);
}
Needed interface for test purpose:
public interface ISenderClass
{
void SendMessage(int element);
void AddToQueue(int element);
}
There's a very simple solution, saying I have created my class incorrect due to the Single Responsability Principle, and my class' purpose is not to send messages, but actually run what sends them.
What I should have, is another class, TransmittingClass, which exposes the method SendMessage(int) through its own interface.
This way I can test that class, and SenderClass should just call the method through that interface.
But what other options do I have with the current implementation?
I can make all private methods I wish to test (all of them) have a [assembly:InternalsVisibleTo("MyTests")], but does a third option exist?
Send message logic should be implemented in a separate class with a separate interface. This class should take the new class as a dependency. You can test the new class separately.
public interface IMessageQueue
{
void AddToQueue(int element);
}
public interface IMessageSender
{
void SendMessage(object message);
}
public class SenderClass : IMessageQueue
{
private readonly IMessageSender _sender;
public SenderClass(IMessageSender sender)
{
_sender = sender;
}
public void AddToQueue(int element)
{
/*...*/
}
private void SendMessage()
{
_sender.SendMessage(new object());
}
}
public class DummyMessageSender : IMessageSender
{
//you can use this in your test harness to check for the messages sent
public Queue<object> Messages { get; private set; }
public DummyMessageSender()
{
Messages = new Queue<object>();
}
public void SendMessage(object message)
{
Messages.Enqueue(message);
//obviously you'll need to do some locking here too
}
}
Edit
To address your comment, here is an implementation using Action<int>. This allows you to define your message sending action in your test class to mock the SendMessage method without worrying about creating another class. (Personally, I'd still prefer to define the classes/interfaces explicitly).
public class SenderClass : ISenderClass
{
private Queue<int> _myQueue = new Queue<int>();
private Thread _worker;
private readonly Action<int> _senderAction;
public SenderClass()
{
_worker = new Thread(RunWorker) { IsBackground = true };
_worker.Start();
_senderAction = DefaultMessageSendingAction;
}
public SenderClass(Action<int> senderAction)
{
//Create a background worker
_worker = new Thread(RunWorker) { IsBackground = true };
_worker.Start();
_senderAction = senderAction;
}
private void RunWorker() //This is the background worker's method
{
while (true) //Keep it running
{
lock (_myQueue) //No fiddling from other threads
{
while (_myQueue.Count != 0) //Pop elements if found
SendMessage(_myQueue.Dequeue()); //Send the element
}
Thread.Sleep(50); //Allow new elements to be inserted
}
}
private void SendMessage(int element)
{
_senderAction(element);
}
private void DefaultMessageSendingAction(int item)
{
/* whatever happens during sending */
}
public void AddToQueue(int element)
{
Task.Run(() => //Async method will return at ones, not slowing the caller
{
lock (_myQueue) //Lock queue to insert into it
{
_myQueue.Enqueue(element);
}
});
}
}
public class TestClass
{
private SenderClass _sender;
private Queue<int> _messages;
[TestInitialize]
public void SetUp()
{
_messages = new Queue<int>();
_sender = new SenderClass(DummyMessageSendingAction);
}
private void DummyMessageSendingAction(int item)
{
_messages.Enqueue(item);
}
[TestMethod]
public void TestMethod1()
{
//This isn't a great test, but I think you get the idea
int message = 42;
_sender.AddToQueue(message);
Thread.Sleep(100);
CollectionAssert.Contains(_messages, 42);
}
}
It looks like SenderClass should not perform any sending at all. It should simply maintain the queue. Inject an Action<int> through the constructor that does the sending. That way you can move SendMessage somewhere else and call it however you like.
As an added benefit your test of SendMessage is not cluttered with queue management.
Seeing your edit you don't seem to like this approach and you don't seem to like the InternalsVisibleTo approach either. You could expose SendMessage through a separate interface and implement that interface explicitly. That way SendMessage is still callable through that interface but by default it is not accessible without some casting contortions. It also does not show up in the intellisense autocomplete list.

How to create a thread in c#

Can I create a class that inherited from thread class in c#, for my Windows Phone application.
For example :
if my class name is 'MyClass' I want to start the thread as new MyClass().Start();
Like in following Java example
public class TagIndexer
{
private static class Task
{
private String docId;
private String tags;
private String extension;
public Task(String docId, String tags, String extension)
{
this.docId = docId;
this.tags = tags;
this.extension = extension;
}
}
private static final LinkedList<Task> queue = new LinkedList<Task>();
private static boolean isWorking = false;
private static class TaskRunner extends Thread
{
#Override
public void run()
{
while (true)
{
Task task;
synchronized (queue)
{
task = queue.poll();
if (null == task)
{
isWorking = false;
break;
}
isWorking = true;
}
/*
* PROCESSING CODE
*/
}
}
}
public static void addDocument(int docId, String tags, String extension)
{
Task task = new Task(Integer.toString(docId), tags, extension);
synchronized (queue)
{
queue.add(task);
if (!isWorking)
{
new TaskRunner().start();
}
}
}
}
new MyClazz().Start();
-
public abstract class MyThread
{
public abstract void Run();
public void Start()
{
new Thread(Run).Start();
}
}
public class MyClazz : MyThread
{
public override void Run()
{
Console.WriteLine("Hello World");
}
}
On Windows Phone, Thread is a sealed class, therefore you cannot inherit from it. If you want to keep the task-based approach, you can just create a class that will wrap a thread instance. Something like:
public abstract class Task
{
protected Thread InternalThread { get; set; }
protected abstract void Run();
public void Start()
{
this.InternalThread = new Thread(this.Run);
this.InternalThread.Start();
}
}
Of course, it's just an example. You would have to add some synchronization mechanism to prevent the Start method from creating multiple threads if called more than once.
Then you can inherit it to create custom tasks:
public class MyTask : Task
{
protected override void Run()
{
// Do something
}
}
See this article about BackgroundAgent from MSDN:
Background Agents Overview for Windows Phone

Categories

Resources