I am currently migrating java code for my android app to C#. I want to update my UI in middle of thread execution.
Here is my java code:-
private Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == MSG_SURFACE_CREATED) {
contentWidth = 0;
contentHeight = 0;
requestLayout();
return true;
} else {
Log.w("Unknown msg.what: " + msg.what);
}
return false;
}
});
And:-
void postChangedToView(final int indexInAdapter) {
handler.post(new Runnable() {
#Override
public void run() {
changedToView(indexInAdapter, true);
}
});
}
I have tried something like this in c# :-
private Android.OS.Handler handler = new Android.OS.Handler();
private class Callback : Android.OS.Handler.ICallback //inner class
{
ViewController fp; //Create instance of outer class
public Callback(FViewController _fp) //pass the instance to constructor of inner class
{
fp = _fp;
}
#region ICallback implementation
public bool HandleMessage (Message msg)
{
if (msg.What == MSG_SURFACE_CREATED)
{
contentWidth = 0;
contentHeight = 0;
fp.RequestLayout ();
return true;
}
else
{
Log.w("Unknown msg.what: " + msg.What);
}
return false;
throw new NotImplementedException ();
}
}
Here I cannot make an inline class of Handler.ICallBack
And:-
internal virtual void postChangedToView(int indexInAdapter) {
handler.Post (Task.Run (()=> flippedToView (indexInAdapter,true)));
}
Here I get an error saying :-
Error CS1503: Argument 1: cannot convert from 'System.Threading.Tasks.Task' to 'System.Action'
Handler.Post requires a System.Action parameter. You can create System.Action as below:
internal virtual void postFlippedToView(int indexInAdapter)
{
Action action = () => flippedToView(indexInAdapter, true);
handler.Post (action );
}
Related
My code:
abstract class StateMachine {
protected string State { get; private set; }
protected abstract void OnWorking();
protected abstract void OnPrepare();
protected abstract void OnCancel();
public bool Prepare() {
if(State != null) {
return false;
}
State = "Preparing";
OnPrepare();
State = "Prepared";
return true;
}
public bool Start() {
if(State != "Prepared") {
return false;
}
State = "Working";
OnWorking();
State = "Done";
return true;
}
public bool Cancel() {
if(State != "Working" || State == "Done") {
return false;
}
OnCancel();
State = "Canceled";
return true;
}
}
class Downloader : StateMachine {
protected override void OnPrepare() {
Console.WriteLine("I am preparing.");
Thread.Sleep(1000);
}
protected override void OnWorking() {
Console.WriteLine("I am working.");
Thread.Sleep(1000);
}
protected override void OnCancel() {
Console.WriteLine("Let's cancel the operation!");
}
}
class Program {
static void Main(string[] args) {
Downloader downloader = new Downloader();
Parallel.Invoke(() => {
downloader.Prepare();
downloader.Start();
}, () => {
// Cancel while working
Thread.Sleep(1500);
downloader.Cancel();
});
}
}
The output would be:
I am preparing.
I am working.
Let's cancel the operation!
Now I am building the StateMachine class and it works very well. It allows subclasses to not care about the current states at all, which is awesome because handling states of a process is a huge pain in the head.
The problem is though, nothing can't stop the subclass (Downloader) from calling those protected methods in the base class (StateMachine) by itself. For example, a subclass can have something like:
protected override void OnWorking(){
Console.WriteLine("I am working.");
Thread.Sleep(1000);
OnCancel();
OnPrepare();
}
Then the output would be:
I am preparing.
I am working.
Let's cancel the operation!
I am preparing.
Let's cancel the operation!
Which is not expected from the StateMachine's point of view.
So I am trying to prevent the subclass from calling protected methods. But I feel like I am doing a weird thing. I don't think C# OOP concepts would allow this behavior.
I don't mean to make these protected methods invisible from the subclass though. I'm more about throwing exceptions if subclasses do that. Maybe I need to add extra logic in the base class the handle this. But that might makes the code messy.
What would you do in this situation? I mean, what might be the elegant way to solve this?
You can define them as delegates and make them private, and set them with abstract helper methods as follow:
static void Main()
{
Downloader downloader = new Downloader();
Parallel.Invoke(() =>
{
downloader.Prepare();
downloader.Start();
}, () =>
{
// Cancel while working
Thread.Sleep(1500);
downloader.Cancel();
});
}
abstract class StateMachine
{
protected string State { get; private set; }
private Action OnWorking;
private Action OnPrepare;
private Action OnCancel;
// Helper methods to be implemented in subclass
protected abstract Action DefineWorkingAction();
protected abstract Action DefinePrepareAction();
protected abstract Action DefineCancelAction();
protected StateMachine()
{
this.OnWorking = DefineWorkingAction();
this.OnPrepare = DefinePrepareAction();
this.OnCancel = DefineCancelAction();
}
public bool Prepare()
{
if (State != null)
{
return false;
}
State = "Preparing";
OnPrepare();
State = "Prepared";
return true;
}
public bool Start()
{
if (State != "Prepared")
{
return false;
}
State = "Working";
OnWorking();
State = "Done";
return true;
}
public bool Cancel()
{
if (State != "Working" || State == "Done")
{
return false;
}
OnCancel();
State = "Canceled";
return true;
}
}
class Downloader : StateMachine
{
protected override Action DefineWorkingAction()
{
return () =>
{
Console.WriteLine("I am working.");
Thread.Sleep(1000);
};
}
protected override Action DefinePrepareAction()
{
return () =>
{
Console.WriteLine("I am preparing.");
Thread.Sleep(1000);
};
}
protected override Action DefineCancelAction()
{
return () =>
{
Console.WriteLine("Let's cancel the operation!");
};
}
}
Now subclasses cannot call them anymore.
I am working on my own multithreading for my algorithm independed pathfinding for unity. However, when I am executing two the same class I get a memory leak and when only executing one instance I am having no issues. I really want to use at least two threads if it is necessary.
Below is the class I have issues with. Keep in mind, that two independend threads will have to execute parts of this script. AddJob can be called from the main unity thread but will most likely be called from another update thread for the agents.
namespace Plugins.PathFinding.Threading
{
internal class PathFindingThread
{
private Thread m_Worker;
private volatile Queue<CompletedProcessingCallback> m_CallbackQueue;
private volatile Queue<IAlgorithm> m_QueuedTasks;
internal int GetTaskCount
{
get
{
return m_QueuedTasks.Count;
}
}
internal PathFindingThread()
{
m_Worker = new Thread(Run);
m_CallbackQueue = new Queue<CompletedProcessingCallback>();
m_QueuedTasks = new Queue<IAlgorithm>();
}
private void Run()
{
Debug.Log("<b><color=green> [ThreadInfo]:</color></b> PathFinding Thread Started ");
try
{
while(true)
{
if (m_QueuedTasks.Count > 0)
{
IAlgorithm RunningTask = m_QueuedTasks.Dequeue();
RunningTask.FindPath(new IAlgorithmCompleted(AddCallback));
}
else
break;
}
Debug.Log("<b><color=red> [ThreadInfo]:</color></b> PathFinding Worker is idle and has been Stopped");
}
catch(Exception)
{
Debug.Log("<b><color=red> [ThreadInfo]:</color></b> PathFinding thread encountred an error and has been aborted");
}
}
internal void AddJob(IAlgorithm AlgorithmToRun)
{
m_QueuedTasks.Enqueue(AlgorithmToRun);
//Debug.Log("Added Job To Queue");
}
private void AddCallback(CompletedProcessingCallback callback)
{
m_CallbackQueue.Enqueue(callback);
}
private void Update()
{
if (m_CallbackQueue.Count > 0)
{
if (m_CallbackQueue.Peek().m_Callback != null) { }
m_CallbackQueue.Peek().m_Callback.Invoke(m_CallbackQueue.Peek().m_Path);
m_CallbackQueue.Dequeue();
}
if (m_Worker.ThreadState != ThreadState.Running && m_QueuedTasks.Count != 0)
{
m_Worker = new Thread(Run);
m_Worker.Start();
}
}
}
internal delegate void IAlgorithmCompleted(CompletedProcessingCallback callback);
internal struct CompletedProcessingCallback
{
internal volatile FindPathCompleteCallback m_Callback;
internal volatile List<GridNode> m_Path;
}
}
namespace Plugins.PathFinding
{
internal enum TypeOfNode
{
Ground,
Air
}
//used to store location information since array can only take rounded numbers
internal struct Position
{
internal int x;
internal int y;
internal int z;
}
internal class GridNode
{
internal Position M_PostitionInGrid { get; private set; }
internal Vector3 M_PostitionInWorld { get; private set; }
internal TypeOfNode M_type { get; private set; }
internal bool m_IsWalkable = true;
internal GridNode m_ParrentNode;
internal int Hcost;
internal int Gcost;
internal int Fcost { get { return Hcost + Gcost; } }
internal GridNode(Position postion , Vector3 WorldPosition)
{
M_PostitionInGrid = postion;
m_IsWalkable = true;
M_PostitionInWorld = WorldPosition;
}
}
}
internal delegate void FindPathCompleteCallback(List<GridNode> Path);
internal abstract class IAlgorithm
{
protected GridNode m_SavedStart;
protected GridNode m_SavedTarget;
protected List<GridNode> m_LocatedPath;
protected FindPathCompleteCallback m_Callback;
internal FindPathCompleteCallback GetCallback
{
get
{
return m_Callback;
}
}
protected PathFindingGrid m_grid;
internal abstract void FindPath(IAlgorithmCompleted callback);
protected abstract List<GridNode> CreatePath(PathFindingGrid Grid, GridNode Start, GridNode Target);
protected abstract List<GridNode> RetracePath(GridNode start, GridNode target);
}
namespace Plugins.PathFinding.Astar
{
internal class AstarFinder : IAlgorithm
{
//construction of the Algorithm
internal AstarFinder(GridNode start, GridNode target, FindPathCompleteCallback Callback)
{
m_SavedStart = start;
m_SavedTarget = target;
m_Callback = Callback;
m_LocatedPath = new List<GridNode>();
m_grid = PathFindingGrid.GetInstance;
}
//function to start finding a path
internal override void FindPath(IAlgorithmCompleted callback)
{
//running Algorithm and getting the path
m_LocatedPath = CreatePath(PathFindingGrid.GetInstance, m_SavedStart, m_SavedTarget);
callback.Invoke(
new CompletedProcessingCallback()
{
m_Callback = m_Callback,
m_Path = m_LocatedPath
});
}
//Algorithm
protected override List<GridNode> CreatePath(PathFindingGrid Grid, GridNode Start, GridNode Target)
{
if(Grid == null ||
Start == null ||
Target == null)
{
UnityEngine.Debug.Log("Missing Parameter, might be outside of grid");
return new List<GridNode>();
}
List<GridNode> Path = new List<GridNode>();
List<GridNode> OpenSet = new List<GridNode>();
List<GridNode> ClosedSet = new List<GridNode>();
OpenSet.Add(Start);
int Retry = 0;
while (OpenSet.Count > 0)
{
if(Retry > 3000 || Grid == null)
{
UnityEngine.Debug.Log("Path Inpossible Exiting");
break;
}
GridNode CurrentNode = OpenSet[0];
for (int i = 0; i < OpenSet.Count; i++)
{
if(OpenSet[i].Fcost < CurrentNode.Fcost || OpenSet[i].Fcost == CurrentNode.Fcost && OpenSet[i].Hcost < CurrentNode.Hcost)
{
CurrentNode = OpenSet[i];
}
}
OpenSet.Remove(CurrentNode);
ClosedSet.Add(CurrentNode);
if(CurrentNode == Target)
{
Path = RetracePath(CurrentNode,Start);
break;
}
GridNode[] neighbour = Grid.GetNeighbouringNodes(CurrentNode);
for (int i = 0; i < neighbour.Length; i++)
{
if (!neighbour[i].m_IsWalkable || ClosedSet.Contains(neighbour[i]))
continue;
int CostToNeighbour = CurrentNode.Gcost + Grid.GetDistance(CurrentNode, neighbour[i]);
if(CostToNeighbour < neighbour[i].Gcost || !OpenSet.Contains(neighbour[i]))
{
neighbour[i].Gcost = CostToNeighbour;
neighbour[i].Hcost = Grid.GetDistance(neighbour[i], Target);
neighbour[i].m_ParrentNode = CurrentNode;
if (!OpenSet.Contains(neighbour[i]))
OpenSet.Add(neighbour[i]);
}
}
Retry++;
}
return Path;
}
//retracing the path out of a node map
protected override List<GridNode> RetracePath(GridNode start, GridNode target)
{
List<GridNode> Output = new List<GridNode>();
GridNode current = start;
while(current != target)
{
Output.Add(current);
current = current.m_ParrentNode;
}
Output.Reverse();
return Output;
}
}
}
This shows the core of your code made thread safe.
internal class PathFindingThread
{
Task m_Worker;
ConcurrentQueue<CompletedProcessingCallback> m_CallbackQueue;
ConcurrentQueue<IAlgorithm> m_QueuedTasks;
internal int GetTaskCount
{
get
{
return m_QueuedTasks.Count;
}
}
internal PathFindingThread()
{
m_CallbackQueue = new ConcurrentQueue<CompletedProcessingCallback>();
m_QueuedTasks = new ConcurrentQueue<IAlgorithm>();
m_Worker = Task.Factory.StartNew(() =>
{
while (true)
{
IAlgorithm head = null;
if (m_QueuedTasks.TryDequeue(out head))
{
head.FindPath(new IAlgorithmCompleted(AddCallback));
}
else
{
Task.Delay(0);
}
}
});
}
internal void AddJob(IAlgorithm AlgorithmToRun)
{
m_QueuedTasks.Enqueue(AlgorithmToRun);
}
private void AddCallback(CompletedProcessingCallback callback)
{
m_CallbackQueue.Enqueue(callback);
}
private void Update()
{
CompletedProcessingCallback cb = null;
if (m_CallbackQueue.TryDequeue(out cb))
{
cb.m_Callback.Invoke(cb.m_Path);
}
}
}
Volatile is only good for changing the value of the field - not calling methods on a collection that is referenced by the field.
You propably do not need to have Volatile in CompletedProcessingCallback, but it depends where else this is used. Certainly having volatile on a struct field is a bad smell.
Resolve these thread issues first, then see if you still have the problem.
I have custom thread which parses WiFi networks and updates the UI (DataGridView and graphs). Here is the thread method:
private void RefreshThread()
{
var watch = Stopwatch.StartNew();
while (true)
{
UpdateAllNetworks();
UpdateAllInterferences();
UpdateAllColors();
switch (ActivePage)
{
case Page.Start:
break;
case Page.Networks:
this.Invoke((MethodInvoker)delegate
{
UpdateDataGridWithNetworks();
ClearGraphs();
Draw24GHzGraph();
DrawSignalsOverTimeGraph();
});
break;
case Page.Channels:
break;
case Page.Analyze:
break;
default:
break;
}
watch.Stop();
int elapsedMs = (int) watch.ElapsedMilliseconds;
if (elapsedMs < Constants.NetworksRefreshThreadInterval)
Thread.Sleep(Constants.NetworksRefreshThreadInterval - elapsedMs);
}
}
Custom DataGridView:
public class CustomDataGridView : DataGridView
{
...
protected override void OnCellClick(DataGridViewCellEventArgs e)
{
base.OnCellClick(e);
int Index = e.RowIndex;
if (Index != -1)
{
DataGridViewRow row = Rows[Index];
PrimaryKeyForSelectedRow = row.Cells[KeyName].Value.ToString();
}
}
}
The DataGridView is my custom DataGrid where I have a click event handler. I have observed that sometimes the event handler isn't called but in most cases it is.
What could be the problem? Is it related to multithreading or the event isn't queued?
Your code blocks main thread, use separate thread for your network details update. Here is quick sample how it done.
class Program
{
static void Main(string[] args)
{
var helper = new Looper(5000, YourMethod_RefreshThread);
helper.Start();
}
private static void YourMethod_RefreshThread()
{
Console.WriteLine(DateTime.Now);
}
}
public class Looper
{
private readonly Action _callback;
private readonly int _interval;
public Looper(int interval, Action callback)
{
if(interval <=0)
{
throw new ArgumentOutOfRangeException("interval");
}
if(callback == null)
{
throw new ArgumentNullException("callback");
}
_interval = interval;
_callback = callback;
}
private void Work()
{
var next = Environment.TickCount;
do
{
if (Environment.TickCount >= next)
{
_callback();
next = Environment.TickCount + _interval;
}
Thread.Sleep(_interval);
} while (IsRunning);
}
public void Start()
{
if (IsRunning)
{
return;
}
var thread = new Thread(Work);
thread.Start();
IsRunning = true;
}
public void Stop()
{
this.IsRunning = false;
}
public bool IsRunning { get; private set; }
I have implemented callbacks on Handler(in java). I need to implement the same on c#(Xamarin). But as of now I am unable to find any solution to how I can do this in C#. I am new to c# hence have very little knowledge.
here is the java code:-
private Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg)
{
if (msg.what == MSG_SURFACE_CREATED)
{
contentWidth = 0;
contentHeight = 0;
requestLayout();
return true;
}
else
{
Log.w("Unknown msg.what: " + msg.what);
}
return false;
}
});
Any idea can i implement the same in C#?
Events is the way to go (which uses delegates). Here is some sample code:
class CallingClass
{
private SurfaceCreatingClass m_surfacecreatingclass;
public CallingClass()
{
m_surfacecreatingclass = new SurfaceCreatingClass();
m_surfacecreatingclass.SurfaceCreatedHandler += OnFinished;
m_surfacecreatingclass.CreateSurface();
}
void OnFinished(int iMessageWhat)
{
if (iMessageWhat == SurfaceCreatingClass.MSG_SURFACE_CREATED)
{
contentWidth = 0;
contentHeight = 0;
RequestLayout();
}
else
{
Log.w("Unknown msg.what: " + iMessageWhat);
}
}
}
class SurfaceCreatingClass
{
public delegate void SurfaceCreatedDelegate(int iWhat);
public event SurfaceCreatedDelegate SurfaceCreatedHandler;
public const int MSG_SURFACE_CREATED = 1;
public void CreateSurface()
{
/////////////////////////////
// Surface creation code here
// ...
/////////////////////////////
if (SurfaceCreatedHandler != null)
SurfaceCreatedHandler(MSG_SURFACE_CREATED);
}
}
IN Xamarin You still will use this " inline " approach, defined by the keyword "delegate".
This is, because, callbacks are function pointers, c# supports this, java not, and xamarin also not, BUT tries to spawn a bridge.
Delegates in xamarin are described in here:
http://docs.xamarin.com/guides/ios/application_fundamentals/delegates,_protocols,_and_events/
I have 2 classes A and B, where they belongs to the same namespace but resides in seperate files namely a.cs and b.cs, where class B essentially is a helper wrapping a web service call as follow:
public class A
{
public A() // constructor
{
protected static B b = new B();
}
private void processResult1(string result)
{
// come here when result is successful
}
private void processResult2(string result)
{
// come here when result is failed
}
static void main()
{
b.DoJobHelper(...);
}
}
public class B
{
private com.nowhere.somewebservice ws;
public B()
{
this.ws = new com.nowhere.somewebservice();
ws.JobCompleted += new JobCompletedEventHandler(OnCompleted);
}
void OnCompleted(object sender, JobCompletedEventArgs e)
{
string s = e.Result;
Guid taskID = (Guid)e.UserState;
switch (s)
{
case "Success":
// Call processResult1();
break;
case "Failed":
// Call processResult2();
break;
default: break;
}
}
public void DoJobHelper()
{
Object userState = Guid.NewGuid();
ws.DoJob(..., userState);
}
}
(1) I have seen texts on the net on using delegates for callbacks but failed to apply that to my case. All I want to do is to call the appropriate processResult() method upon OnCompleted() event, but dunno how to and where to declare the delegate:
public delegate void CallBack(string s);
(2) There is a sender object passed in to OnCompleted() but never used, did I miss anything there? Or how can I make good use of sender?
Any helps appreciated.
1)
public class A
{
public A() // constructor
{
protected static B b = new B(processResult1, processResult2);
}
private void processResult1(string result)
{
// come here when result is successful
}
private void processResult2(string result)
{
// come here when result is failed
}
static void main()
{
b.DoJobHelper(...);
}
}
public class B
{
private com.nowhere.somewebservice ws;
private Action<string> success;
private Action<string> failure;
public B(Action<string> success, Action<string> failure)
{
this.success = success;
this.failure = failure;
this.ws = new com.nowhere.somewebservice();
ws.JobCompleted += new JobCompletedEventHandler(OnCompleted);
}
void OnCompleted(object sender, JobCompletedEventArgs e)
{
string s;
Guid taskID = (Guid)e.UserState;
//this switch will never do anything because s is null right now.
//you'll need to check some actual state, or translate some other
//state into the "Success" and "Failure" words for the s variable
//before you call this switch statement.
switch (s)
{
case "Success":
{
success(s);
break;
}
case "Failed":
{
failure(s);
break;
}
default: break;
}
}
public void DoJobHelper()
{
Object userState = Guid.NewGuid();
ws.DoJob(..., userState);
}
}
2) don't bother using sender. it's only important if you have more than one object's events being handled by the same event handler method.