Task start/stop handling using abstract classes - c#

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

Related

C# threading - Main Thread gets stuck in inf loop

I'm running into a problem with my threading for my simple incremental game.
when I begin the thread it does not seem to be starting an actual thread so I get stuck in the endless loop in the thread RunThread method.
the way I'm doing threading in c# is inheriting from this base thread class somebody else on SO gave this code to allow you to inherit from Thread.
abstract class BaseThread
{
private Thread _thread;
protected BaseThread()
{
_thread = new Thread(new ThreadStart(this.RunThread));
}
// Thread methods / properties
public void Start() => _thread.Start();
public void Join() => _thread.Join();
public bool IsAlive => _thread.IsAlive;
// Override in base class
public abstract void RunThread();
}
that base thread is then inherited from. Person inherits from Base Thread.
abstract class Person : BaseThread
{
public BigInteger amt = new BigInteger(0);
public BigInteger pow = new BigInteger(1);
public BigInteger cost = new BigInteger(100);
public ResourceManagement res= ResourceManagement.Instance;
public static bool PeopleThreads = true;
public override void RunThread()
{
}
}
and at the lowest level, I have a Farmer this inherits from Person.
class Farmer : Person
{
public override void RunThread()
{
while (PeopleThreads)
{
Thread.Sleep(5000);
res.AddFood(amt * pow);
Thread.Sleep(5000);
res.AddFood(amt * pow);
res.subtractFromRes("Food", amt);
}
}
}
in my Thread manager class I am doing farmer.RunThread(); it seems to get me stuck in the while loop instead of creating a new thread. This is my first real attempt at c# threading ive done java threading before and thats why I wanted to be able to inherit from Thread. here is where I start my threads at.
class PeopleManager
{
Farmer farmers = new Farmer();
Lumberjack jacks = new Lumberjack();
Miner miners = new Miner();
private static PeopleManager people_Instance= new PeopleManager();
bool running = false;
static PeopleManager() { }//DO NOT PUT ANYTHING HERE
private PeopleManager() { }//DO NOT PUT ANYTHING HERE
public void StartThreads()
{
if (!running)
{
farmers.RunThread();
jacks.RunThread();
miners.RunThread();
running = true;
}
}
public static PeopleManager Instance { get{ return people_Instance; } }
I fixed my issue changed how I was running the threads from runThread to Start()
class PeopleManager
{
Farmer farmers = new Farmer();
Lumberjack jacks = new Lumberjack();
Miner miners = new Miner();
private static PeopleManager people_Instance= new PeopleManager();
bool running = false;
static PeopleManager() { }//DO NOT PUT ANYTHING HERE
private PeopleManager() { }//DO NOT PUT ANYTHING HERE
public void StartThreads()
{
if (!running)
{
farmers.Start(); //this instead of RunThread() made it run it
jacks.Start(); // run as a thread and not a method call
miners.Start();
running = true;
}
}
public static PeopleManager Instance { get{ return people_Instance; } }

How to make a class that implements IRunnable more generic?

I have the following class:
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private MainActivity mainActivity;
public MyRunnable(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public void Run()
{
mainActivity.RunOnUiThread(() =>
{
mainActivity.ShowAlert();
});
}
}
Then I start it in OnCreate method like that:
MyRunnable myRunnable = new MyRunnable(this);
Java.Lang.Thread thread = new Java.Lang.Thread(myRunnable);
thread.Start();
But the class is too tied up with MainActivity and ShowAlert method. If I want to work with another activity and another method for example:
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private (SomeActivity) someActivity;
public MyRunnable((SomeActivity) someActivity)
{
this.someActivity = someActivity;
}
public void Run()
{
someActivity.RunOnUiThread(() =>
{
mainActivity.(SomeOtherMethod)();
});
}
}
I wouldn't be able to. Is there any way to make it more generic? (I'm using Xamarin.Android)
A simple way is to create an Action-based runnable, passing the Action as a parameter to the runnable .actr (you can also pass additional params, etc...)
C# Action in Java Runnable
public class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
readonly WeakReference<Action> actionRef;
public MyRunnable(Action action)
{
actionRef = new WeakReference<Action>(action);
}
public void Run()
{
actionRef.TryGetTarget(out Action action);
action?.Invoke();
}
}
Usage:
var runnable = new MyRunnable(async () =>
{
// Do whatever you need to do, including capturing of local vars, app/activity context, etc.
await Task.Delay(1000);
Toast.MakeText(this, "In runnable", ToastLength.Long).Show();
~~~
});
runnable.Run();
It seems that it would be easy to implement an interface-based approach:
public interface IRunnableActivity
{
void Run();
}
public class MainActivity : Activity, IRunnableActivity
{
...
public void Run()
{
ShowAlert();
}
}
public class SomeOtherActivity : Activity, IRunnableActivity
{
...
public void Run()
{
SomeOtherMethod();
}
}
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private IRunnableActivity activity;
public MyRunnable(IRunnableActivity runnableActivity)
{
activity = runnableActivity;
}
public void Run()
{
runnableActivity.RunOnUiThread(() =>
{
runnableActivity.Run();
});
}
}
I'll leave you the exercise of deciding how best to get RunOnUiThread with this approach.
You need to decouple ShowAler from MainActivity, create a Utils class, and add the method:
class Utils
{
public static void ShowAlert()
{
Android.Util.Log.Error("lv", "=======");
}
}
In your MyRunnable class, use the base class Activity to achieve polymorphism
public class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
Activity mActivity;
public MyRunnable(Activity activity)
{
mActivity = activity;
}
public void Run()
{
mActivity.RunOnUiThread(() =>
{
Utils.ShowAlert();
}
);
}
}
And then you can use the under code in any Activities:
Thread thread = new Thread(new MyRunnable(this));
thread.Start();

Cancellation async in IDisposable class

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

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