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
Related
how to send verificationId from SendOtpCodeAsync() to SendCode_Button_Clicked()
Share Project code
IAuth auth;
auth = DependencyService.Get<IAuth>();
private async void SendCode_Button_Clicked(object sender, EventArgs e)
{
bool result = await auth.SendOtpCodeAsync(PhonenumberEntry.Text);
}
android project code
[assembly: Dependency(typeof(AuthDriod))]
namespace TestApp_MiniApps.Droid
{
public class AuthDriod : PhoneAuthProvider.OnVerificationStateChangedCallbacks, IAuth
{
private TaskCompletionSource<bool> _phoneAuthTcs;
public Task<bool> SendOtpCodeAsync(string phonenumber)
{
_phoneAuthTcs = new TaskCompletionSource<bool>();
Java.Lang.Long num = (Java.Lang.Long)60;
PhoneAuthOptions options =
PhoneAuthOptions.NewBuilder(FirebaseAuth.Instance)
.SetPhoneNumber(phonenumber) // Phone number to verify
.SetTimeout(num, TimeUnit.Seconds) // Timeout and unit
.SetActivity(Platform.CurrentActivity) // Activity (for callback binding)
.SetCallbacks(this) // OnVerificationStateChangedCallbacks
.Build();
PhoneAuthProvider.VerifyPhoneNumber(options);
return _phoneAuthTcs.Task;
}
public override void OnVerificationCompleted(PhoneAuthCredential credential)
{
}
public override void OnVerificationFailed(FirebaseException exception)
{
_phoneAuthTcs?.TrySetResult(false);
}
public override void OnCodeSent(string verificationId, PhoneAuthProvider.ForceResendingToken forceResendingToken)
{
base.OnCodeSent(verificationId, forceResendingToken);
_phoneAuthTcs?.TrySetResult(true);
}
}//end of class
}
share project interface
namespace TestApp_MiniApps.Views.Xamarin.FireBase
{
public interface IAuth
{
Task<bool> SendOtpCodeAsync(string phonenumber);
}//end of class
}
To summarise what Leo had put in the comments you can check what is returned from your method call.
Change from bool to your own class. For the purpose of this answer I will call it OtpResult.
// The new class definition:
public class OtpResult
{
public bool Success { get; set; }
// Define whatever you like here
public string StringValue { get; set; }
}
public interface IAuth
{
Task<OtpResult> SendOtpCodeAsync(string phonenumber);
}
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
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; } }
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();
I have a viewModel with async Task. I don't now how to test it.
public class MyViewModel : BindableBase
{
public MyViewModel()
{
this.PropertyChanged += MyViewModel_PropertyChanged;
}
private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Action action = async () => await DoSomething();
action();
}
public const string BeforeKey = "before";
public const string AfterKey = "After";
public string Status { get; private set; } = BeforeKey;
public async Task DoSomething()
{
await Task.Delay(3000);
Status = AfterKey;
}
string bindagleProp;
public string BindagleProp
{
get { return bindagleProp; }
set { SetProperty(ref bindagleProp, value); }
}
}
Here is my test:
[TestMethod]
public async Task TestMyViewModel()
{
MyViewModel viewModel = new MyViewModel();
Assert.AreEqual(viewModel.Status, MyViewModel.BeforeKey, "before check");
viewModel.BindagleProp = "abc";
Assert.AreEqual(viewModel.Status, MyViewModel.AfterKey, "after check");
}
The test failed because it's not waiting to completion of the task.
I DON'T want to use Task.Delay in the unit test, because it's not safety. DoSomething method can has unknown duration time.
Thank you for any help.
Edit:
In fact, The issue is not specific for MVVM, but for any async event handler.
For example:
// class with some logic, can be UI or whatever.
public class MyClassA
{
Size size;
public Size Size
{
get { return size; }
set
{
size = value;
SizeChanged?.Invoke(this, EventArgs.Empty);
}
}
public event EventHandler SizeChanged;
}
// this class uses the MyClassA class.
public class MyCunsomerClass
{
readonly MyClassA myClassA = new MyClassA();
public MyCunsomerClass()
{
myClassA.SizeChanged += MyClassA_SizeChanged;
}
public string Status { get; private set; } = "BEFORE";
private async void MyClassA_SizeChanged(object sender, EventArgs e)
{
await LongRunningTaskAsync();
Status = "AFTER";
}
public async Task LongRunningTaskAsync()
{
await Task.Delay(3000);
///await XYZ....;
}
public void SetSize()
{
myClassA.Size = new Size(20, 30);
}
}
Now, I want to test it:
[TestMethod]
public void TestMyClass()
{
var cunsomerClass = new MyCunsomerClass();
cunsomerClass.SetSize();
Assert.AreEqual(cunsomerClass.Status, "AFTER");
}
The test failed.
I asked Stehphen Cleary [The famous professor of asynchronous], and he answered me:
If by "async event handler" you mean an async void event handler,
then no, those aren't testable. However, they are often useful in a UI
application. So what I usually end up doing is having all my async
void methods be exactly one line long. They all look like this:
async void SomeEventHandler(object sender, EventArgsOrWhatever args)
{
await SomeEventHandlerAsync(sender, args);
}
async Task SomeEventHandlerAsync(object sender, EventArgsOrWhatever args)
{
... // Actual handling logic
}
Then the async Task version is unit testable, composable, etc. The
async void handler isn't, but that's acceptable since it no longer
has any real logic at all.
Thanks Stephen! Your idea is excellent!
Ok So first of all, I would move the worker out to an other class and make an interface to it. So that when I run the test I can inject another worker!
public class MyViewModel : BindableBase
{
private IWorker _worker;
private readonly DataHolder _data = new DataHolder(){Test = DataHolder.BeforeKey};
public string Status { get { return _data.Status; } }
public MyViewModel(IWorker worker = null)
{
_worker = worker;
if (_worker == null)
{
_worker = new Worker();
}
this.PropertyChanged += MyViewModel_PropertyChanged;
}
private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Action action = async () => await _worker.DoSomething(_data);
action();
}
string bindagleProp;
public string BindagleProp
{
get { return bindagleProp; }
set { SetProperty(ref bindagleProp, value); }
}
}
public class DataHolder
{
public const string BeforeKey = "before";
public const string AfterKey = "After";
public string Status;
}
public interface IWorker
{
Task DoSomething(DataHolder data);
}
public class Worker : IWorker
{
public async Task DoSomething(DataHolder data)
{
await Task.Delay(3000);
data.Status = DataHolder.AfterKey;
}
}
Now the inject code would look something like:
[TestMethod]
public async Task TestMyViewModel()
{
TestWorker w = new TestWorker();
MyViewModel viewModel = new MyViewModel(w);
Assert.AreEqual(viewModel.Status, DataHolder.BeforeKey, "before check");
viewModel.BindagleProp = "abc";
Assert.AreEqual(viewModel.Status, DataHolder.AfterKey, "after check");
}
public class TestWorker : IWorker
{
public Task DoSomething(DataHolder data)
{
data.Status = DataHolder.BeforeKey;
return null; //you maybe should return something else here...
}
}