Access from my main form class into specific class method - c#

This is my main form class and inside i have Stop button click event:
public partial class MainWin : Form
{
private Job job = new...
private void btnStop_Click(object sender, EventArgs e)
{
job.state = true;
}
}
When my stop button clicked i change my job class member from false to true and what i want to do is when this variable changed to true i want to access to specific method inside job class and do something.
public class Job
{
public bool state { get; set; }
private void processFile() // i want access to this method in order to change other class state
{
// do work
}
}
how can i do it ?

It's really hard to tell what you exactly mean, but one way to invoke a method when the property is set would be to expand the auto property out and do exactly that.
public class Job
{
private bool state;
public bool State
{
get { return this.state; }
set
{
this.state = value;
processFile();
}
private void processFile()
{
// do work
}
}
However, just guessing and seeing this little bit of code, you might want to redesign how you're doing things.

If really don't want to expose you private method, you can do something like this:
public class Job
{
private bool state;
public bool State
{
get
{
return state;
}
set
{
if (state != value)
{
state = value;
OnStateChanged();
}
}
}
private void OnStateChanged()
{
if (state) // or you could use enum for state
Run();
else
Stop();
}
private void Run()
{
// run
}
private void Stop()
{
// stop
}
}
But you should really consider creating public Job.Run method and leaving Job.State readonly. If you want the object to perform some operations, the methods will be more suitable for this.

Create the Job class like this:
public class Job
{
private bool _isRunning = false;
public bool IsRunning { get { return _isRunning; } }
public void StartProcessing()
{
if (_isRunning)
{
// TODO: warn?
return;
}
ProcessFile();
}
public void StopProcessing()
{
if (!_isRunning)
{
// TODO: warn?
return;
}
// TODO: stop processing
}
private void ProcessFile()
{
_isRunning = true;
// do your thing
_isRunning = false;
}
}
Then consume it like this:
public partial class MainWin : For
{
private Job _job = new Job();
private void StartButton_Click(object sender, EventArgs e)
{
if(!_job.IsRunning)
{
_job.StartProcessing();
}
}
private void StopButton_Click(object sender, EventArgs e)
{
if(_job.IsRunning)
{
_job.StopProcessing();
}
}
}
Thread safety left out as exercise.

Related

C# bool and turn on off function with neat way?

I got following code.
public class MpChange : CusEffect
{
bool AlreadyDo = false;
bool AlreadyStop = false;
public override void CondDel(object sender, CondEventArgs e)
{
if (e.CondMet && !AlreadyDo)
{
DoEffect();
AlreadyDo = true;
AlreadyStop = false;
}
else if (!e.CondMet && !AlreadyStop)
{
StopEffect();
AlreadyStop = true;
AlreadyDo = false;
}
}
public override void DoEffect()
{
Debug.Log(WhoEffect.name + "'s Mp changed +5");
}
public override void StopEffect()
{
Debug.Log(WhoEffect.name + "'s Mp changed -5");
}
}
This is called when character's hp is full, (then DoEffect()), and if not full, then StopEffect().
When character's hp is changed, event published and this MpChange class is subscribe it.
In this case, can this code be neat?
I hate to using this 2 boolean variables (AlreadyDo, AlreadyStop), being confused.
One boolean will do:
bool State = false;
public override void CondDel(object sender, CondEventArgs e)
{
if (e.CondMet == State) return; // nothing to do, state's the current one
State = !State; // flip the flag
if (State) { // do or undo a thing
DoEffect();
} else {
StopEffect();
}
}
So instead using boolean, I should use enum.
I set,
public enum ConditionState
{
None, Complete, Incomplete,
}
and change condition code part based on enum state and prevent duplicate calling,
public abstract class CusCondition
{
public bool Earned;
public int SealValueCond;
public ConditionState conditionMet;
private ConditionState prevCond = ConditionState.None;
[HideInInspector]
public Character WhoCondition;
public virtual void ConditionEvent(object sender, MyEventArgs myEventArgs)
{
SealManager.Instance.PublishEvent(this, new CondEventArgs(conditionMet));
}
public virtual void ConditionEventState(object sender, MyEventArgs myEventArgs)
{ // execute only once state changes
if (conditionMet == prevCond) return;
prevCond = conditionMet;
SealManager.Instance.PublishEvent(this, new CondEventArgs(conditionMet));
}
}
and then at effect part, this is enough.
public override void CondDel(object sender, CondEventArgs e)
{
if (e.CondMet == ConditionState.Complete)
DoEffect();
else if(e.CondMet == ConditionState.Incomplete)
StopEffect();
}

C# - How to prevent a subclass from calling protected methods directly by itself?

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.

How to write NFC tags while preventing WP from launching the action which is currently stored on NFC tag

I trying to allow people to write to NFC tags using my app, so that my app gets launched with a custom parameter. I want to be able to reprogram NFC tags which already have data on them.
I am using the following code but the problem is, that WP always recognizes the action which is already on the NFC tag and interrupts because it wants to launch the NFC tag action which was written anytime before.
How can I tell the OS to stop triggering the action of the tag so that I can immediately rewrite it?
public enum NfcHelperState
{
Initializing,
Waiting,
Ready,
Writing,
Finished,
Error,
NoDeviceFound
}
public class NfcHelper
{
private NfcHelperState _state = NfcHelperState.Initializing;
public NfcHelperState State
{
get { return _state; }
}
private ProximityDevice _nfcDevice;
private long _subscriptionId;
public NfcHelper()
{
Init();
}
public void Init()
{
UpdateState();
_nfcDevice = ProximityDevice.GetDefault();
if (_nfcDevice == null)
{
UpdateState(NfcHelperState.NoDeviceFound);
return;
}
UpdateState(NfcHelperState.Waiting);
}
private void UpdateState(NfcHelperState? state = null)
{
if (state.HasValue)
{
_state = state.Value;
}
if (OnStatusMessageChanged != null)
{
OnStatusMessageChanged(this, _state);
}
}
public void WriteToTag()
{
UpdateState(NfcHelperState.Ready);
_subscriptionId = _nfcDevice.SubscribeForMessage("WriteableTag", WriteableTagDetected);
}
private void WriteableTagDetected(ProximityDevice sender, ProximityMessage message)
{
UpdateState(NfcHelperState.Writing);
try
{
var str = "action=my_custom_action";
str += "\tWindowsPhone\t";
str += CurrentApp.AppId;
_nfcDevice.PublishBinaryMessage("LaunchApp:WriteTag", GetBufferFromString(str),
WriteToTagComplete);
}
catch (Exception e)
{
UpdateState(NfcHelperState.Error);
StopWaitingForTag();
}
}
private void WriteToTagComplete(ProximityDevice sender, long messageId)
{
sender.StopPublishingMessage(messageId);
UpdateState(NfcHelperState.Finished);
StopWaitingForTag();
}
private void StopWaitingForTag()
{
_nfcDevice.StopSubscribingForMessage(_subscriptionId);
}
private static IBuffer GetBufferFromString(string str)
{
using (var dw = new DataWriter())
{
dw.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;
dw.WriteString(str);
return dw.DetachBuffer();
}
}
public delegate void NfcStatusMessageChangedHandler(object myObject, NfcHelperState newState);
public event NfcStatusMessageChangedHandler OnStatusMessageChanged;
}
WriteToTag is called when a button in my app is tapped and the app waits for a writable tag. If a writable tag is recognized, WriteableTagDetected gets called and immediately starts the writing process. However, this is interrupted by the WP dialog which asks whether to perform the NFC action or not. After writing, WriteToTagComplete should be called, where StopWaitingForTag gets called and ends the write process.
I hope you guys can help me :)
Turns out I thought the wrong way. I didn't need to wait for a tag to arrive in order to rewrite it. In fact, there's no need to do _nfcDevice.SubscribeForMessage("WriteableTag", WriteableTagDetected); before writing. Just start using PublishBinaryMessage and it will write to the tag once it arrives at the device.
My final code looks like the following:
public enum NfcHelperState
{
Initializing,
Ready,
WaitingForWriting,
FinishedWriting,
ErrorWriting,
NoDeviceFound
}
public class NfcHelper
{
private NfcHelperState _state = NfcHelperState.Initializing;
public NfcHelperState State
{
get { return _state; }
}
private ProximityDevice _nfcDevice;
private long? _writingMessageId;
public NfcHelper()
{
Init();
}
public void Init()
{
UpdateState();
_nfcDevice = ProximityDevice.GetDefault();
if (_nfcDevice == null)
{
UpdateState(NfcHelperState.NoDeviceFound);
return;
}
UpdateState(NfcHelperState.Ready);
}
private void UpdateState(NfcHelperState? state = null)
{
if (state.HasValue)
{
_state = state.Value;
}
if (OnStatusMessageChanged != null)
{
OnStatusMessageChanged(this, _state);
}
}
public void WriteToTag()
{
StopWritingMessage();
UpdateState(NfcHelperState.WaitingForWriting);
try
{
var str = new StringBuilder();
str.Append("action=my_custom_action");
str.Append("\tWindowsPhone\t{");
str.Append(CurrentApp.AppId);
str.Append("}");
_writingMessageId = _nfcDevice.PublishBinaryMessage("LaunchApp:WriteTag", GetBufferFromString(str.ToString()),
WriteToTagComplete);
}
catch
{
UpdateState(NfcHelperState.ErrorWriting);
StopWritingMessage();
}
}
private void WriteToTagComplete(ProximityDevice sender, long messageId)
{
UpdateState(NfcHelperState.FinishedWriting);
StopWritingMessage();
}
private void StopWritingMessage()
{
if (_writingMessageId.HasValue)
{
_nfcDevice.StopPublishingMessage(_writingMessageId.Value);
_writingMessageId = null;
}
}
private static IBuffer GetBufferFromString(string str)
{
using (var dw = new DataWriter())
{
dw.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;
dw.WriteString(str);
return dw.DetachBuffer();
}
}
public delegate void NfcStatusMessageChangedHandler(object myObject, NfcHelperState newState);
public event NfcStatusMessageChangedHandler OnStatusMessageChanged;
}

Should i pass a Backgroundworker to method

I have an app that has several methods that take a long time to complete. I am using a backgroundworker to run these methods and keep my UI responsive. My methods look something like
public void DoSomething()
{
while( HaveMoreWork )
{
// do work
}
}
Now i want the UI to be able to cancel this at any time so I have changed my methods to take a Backgroundworker like so
public void DoSomething(Backgroundworker worker)
{
while( HaveMoreWork && !worker.CancelationPending )
{
// do work
}
}
My question is, is there a better way to do this. Seems like passing a Backgroundwoker as an argument to all these methods is a bit messy. What is best practice for this?
I am using global variable
private BackgroundWorker _bwSearch = new BackgroundWorker();
private void InitializeBackgroundWorker()
{
_bwSearch = new BackgroundWorker();
_bwSearch.WorkerSupportsCancellation = true;
_bwSearch.DoWork += bwSearch_DoWork;
_bwSearch.RunWorkerCompleted += bwSearch_RunWorkerCompleted;
}
when clicked on stop button
private void btnCancel_Click(object sender, EventArgs e)
{
_bwSearch.Abort();
}
Updated:
Also I am using this simple helper class that is inherited from BackgroundWorker
public class AbortableBackgroundWorker : BackgroundWorker
{
private Thread _workerThread;
protected override void OnDoWork(DoWorkEventArgs e)
{
_workerThread = Thread.CurrentThread;
try
{
base.OnDoWork(e);
}
catch (ThreadAbortException)
{
e.Cancel = true;
Thread.ResetAbort();
}
}
public void Abort()
{
if (_workerThread != null)
{
_workerThread.Abort();
_workerThread = null;
}
}
}
public class DoSomethingService
{
private volatile bool _stopped = false;
public void Start(object socketQueueObject)
{
while (!_stopped)
{
...
}
}
public void Stop()
{
_stopped = true;
}
}
...
var doSomethingService = DoSomethingService();
doSomethingService.Start();
...
doSomethingService.Stop();

Singleton Bindable Controls While Tasking/Multi-Threading

before posting the question i did my research for 10 days so really hope someone can shed some light into solving this issue.
The issue is that any bindable control, does not update once the binding list from singleton class is changed. This is a common issue on multi-threaded apps. Most if not all solutions offer suggestions where the bindlinglist or collection is initialized from parent thread, and then some invocation to be made. Not what i'm looking for. The same issue persist if static class is used instead of singleton.
Basically, the application triggers some Tasks, which in turn create object(s) on different business classes. These objects post messages into the bindinglist, which should update the UI listbox, but does not. And yes, the message object is in the list, and binding after the TASK finished works (items displayed). Locking/unlocking object(s) access is also not an issue.
Appreciate any suggestions/solutions
A trimmed down version of business objects:
namespace MyNameSpace
{
public class Message
{
private string messageSummary;
public Message() { }
public string MessageSummary
{
set { messageSummary = value; }
get { return messageSummary; }
}
}
}
A trimmed down version of another class doing some ops:
namespace MyNameSpace
{
public class WorkDoingClass
{
public WorkDoingClass() { }
public void DoSomeWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSOmrWork Finished";
}
public void DoSomeOtherWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSomeOtherWork Finished";
AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
}
}
}
Singleton:
namespace MyNameSpace
{
public sealed class AllMessages
{
private static readonly AllMessages _instance = new AllMessages();
private BindingList<Message> _allMessagesBL;
public WorkDoingClass() { _allMessagesBL = new BindingList<Message>(); }
public static AllMessages Instance
{
get { return _instance; }
}
public BindingList<Message> AllMessagesBindingList
{
get { return _allMessagesBL};
}
}
}
This is also a trimmed down version from where calls start:
namespace MyNameSpace
{
public partial class Form1 : Form
{
private Task _TaskSqlData;
private CancellationTokenSource cTokenSourceSql;
public Form1()
{
InitializeComponent();
listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
listBox1.DisplayMember = "MessageSummary";
}
private void button1_Click(object sender, EventArgs e)
{
cTokenSourceSql = new CancellationTokenSource();
var tokenSqlData = cTokenSourceSql.Token;
if (this._TaskSqlData != null)
{
if (this._TaskSqlData.Status == TaskStatus.Running)
this.cTokenSourceSql.Cancel();
this._TaskSqlData.Dispose();
this._TaskSqlData = null;
}
_TaskSqlData = Task.Factory.StartNew(()
=> StartDoingWork(this, tokenSqlData, null), tokenSqlData);
}
public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
WorkDoingClass work = new WorkDoingClass();
work.DoSomeOtherWork();
}
Your problem is that the thread(the main UI thread) making the listbox is different from the thread(the worker thread) modifying the collection.
Try the following code. It could solve your issue. I use SynchronizationContext to synchronize the two threads, which serves as the same function with Control.Invoke().
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Task _TaskSqlData;
private CancellationTokenSource cTokenSourceSql;
WorkDoingClass _work;
public Form1()
{
InitializeComponent();
listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
listBox1.DisplayMember = "MessageSummary";
_work = new WorkDoingClass(SynchronizationContext.Current);
}
private void button1_Click(object sender, EventArgs e)
{
cTokenSourceSql = new CancellationTokenSource();
var tokenSqlData = cTokenSourceSql.Token;
if (this._TaskSqlData != null)
{
if (this._TaskSqlData.Status == TaskStatus.Running)
this.cTokenSourceSql.Cancel();
this._TaskSqlData.Dispose();
this._TaskSqlData = null;
}
_TaskSqlData = Task.Factory.StartNew(()
=> StartDoingWork(this, tokenSqlData, null), tokenSqlData);
}
public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
_work.DoSomeOtherWork();
}
}
public class Message
{
private string messageSummary;
public Message() { }
public string MessageSummary
{
set { messageSummary = value; }
get { return messageSummary; }
}
}
public class WorkDoingClass
{
private SynchronizationContext _syncContext;
public WorkDoingClass() { }
public WorkDoingClass(SynchronizationContext _syncContext)
{
// TODO: Complete member initialization
this._syncContext = _syncContext;
}
public void DoSomeWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSOmrWork Finished";
}
public void DoSomeOtherWork()
{
_syncContext.Send(DoWork, null);
}
private static void DoWork(object arg)
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSomeOtherWork Finished";
AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
}
}
public sealed class AllMessages
{
private static readonly AllMessages _instance = new AllMessages();
private BindingList<Message> _allMessagesBL;
public AllMessages() { _allMessagesBL = new BindingList<Message>(); }
public static AllMessages Instance
{
get { return _instance; }
}
public BindingList<Message> AllMessagesBindingList
{
get { return _allMessagesBL; }
}
}
}

Categories