How do I use my own function in a timer class? - winforms

The code is taken from here:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.timer?view=windowsdesktop-6.0
private:
static System::Windows::Forms::Timer^ myTimer = gcnew System::Windows::Forms::Timer;
static int alarmCounter = 1;
static bool exitFlag = false;
// This is the method to run when the timer is raised.
static void TimerEventProcessor( Object^ /*myObject*/, EventArgs^ /*myEventArgs*/ )
{
myTimer->Stop();
// Displays a message box asking whether to continue running the timer.
if ( MessageBox::Show( "Continue running?", String::Format( "Count is: {0}", alarmCounter ), MessageBoxButtons::YesNo ) == DialogResult::Yes )
{
// Restarts the timer and increments the counter.
alarmCounter += 1;
myTimer->Enabled = true;
}
else
{
// Stops the timer.
exitFlag = true;
}
}
For example, after the line myTimer->Stop(); I want to use my own method. How do I identify it? E0020 ID "draw 1" is not defined.
System:: Void Practform::MyForm::draw1() {
. . .
}
Please tell me, because I'm a little stalled, since I've never worked with this.

I have a feeling that what you are bumping up against is attempting to invoke an instance method from a static method. To do so, you would need to have an instance of the class which has the method, e.g:
ref struct Foo {
void InstanceMethod() {}
static void StaticMethod() {
auto instance = gcnew Foo();
instance->InstanceMethod();
}
}
called like so:
Foo::StaticMethod();
However, taking the example code, it could be easier (and more appropriate) to change the static methods to instance methods, like so:
using namespace System;
using namespace System::Windows::Forms;
ref struct MyForm : Form {
Timer ^myTimer = gcnew Timer();
MyForm(void) {
myTimer->Tick += gcnew EventHandler(this, &MyForm::TimerEventProcessor);
myTimer->Interval = 5000;
myTimer->Start();
}
void TimerEventProcessor(Object ^, EventArgs ^) {
myTimer->Stop();
draw1();
}
void draw1() {
MessageBox::Show("Done", "Timer is done", MessageBoxButtons::OK);
}
};
called like so:
auto form = gcnew MyForm();
form->Show();
Notes:
I'm assuming that you've added the code from the example into your own class, called MyForm
I've used struct throughout instead of class to make everything public - you should use the appropriate access modifiers to your use case
The most notable change is the use of the EventHandler constructor which takes an instance of the handler as its first argument, and the method to execute as its second.
The advantages of using instance methods and properties are that:
you will have access to this in the draw1() method (given the name of the method, is likely to want to draw using the form instance), and
the Timer instance will be garbage collected as appropriate,

Related

Updating progressBar using threads and delegate method with arguments in C++/CLI using Visual Studio 2022

I have this code in my Managed C++/Cli in Visual Studio 2022, I want to update the progressBar value in different stages of my c++ function. So far I have 3 delegates UpdateUi(), UpdateUiDone() and UpdateProgress(int percent) which passes an int percent as an argument. These delegates have the methods UiDoSome(), UiDosomeDone() and UpdateProgressBar(int percent). How this code runs is that on a click of a button, a new thread starts which calls the function ThreadProc. SPP is the name of the windows form class. Here is my code:
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
Thread^ t = gcnew Thread(gcnew ThreadStart(this, &SPP::ThreadProc));
t->Start();
}
ThreadProc function:
public: System::Void ThreadProc() {
label6->Invoke(gcnew UpdateUi(this, &SPP::UiDoSome));
-> progressBar1->Invoke(gcnew UpdateProgress(this, &SPP::UpdateProgressBar(25)));
//My code goes in here......
label6->Invoke(gcnew UpdateUiDone(this, &SPP::UiDosomeDone));
}
Delegates definition:
public: delegate void UpdateUi();
public: delegate void UpdateUiDone();
public: delegate void UpdateProgress(int percent);
Delegates' methods:
public: void UiDoSome() {
label6->Text = "processing...";
}
public: void UiDosomeDone() {
label6->Text = "Done!!!";
}
public: void UpdateProgressBar(int percent) {
progressBar1->Value = percent;
}
The problem is that , when invoking the progressBar in the ThreadProc function and I pass a value to the UpdateProgressBar method, the compiler throws an error: "expression must be an lvalue or a function designator". How can I solve this, is this even possible in C++? I know C# has no such issues. I appreciate your help. Thanks in advance.
You need to use an array to pass arguments when using Invoke(), like this:
array<System::Object^>^ params = gcnew array<System::Object^>(1);
params[0] = 25;
Invoke(gcnew UpdateProgress(this, &SPP::UpdateProgressBar), params);
But, you cannot use Invoke() in the first place, since UI elements (buttons, labels etc) can be safely modified only from the thread they were created by. Therefore, you have to use BeginInvoke() here. Also, you can use BeginInvoke of the form itself:
public: System::Void ThreadProc() {
BeginInvoke(gcnew UpdateUi(this, &SPP::UiDoSome));
array<System::Object^>^ params = gcnew array<System::Object^>(1);
params[0] = 25;
BeginInvoke(gcnew UpdateProgress(this, &SPP::UpdateProgressBar), params);
BeginInvoke(gcnew UpdateUiDone(this, &SPP::UiDosomeDone));
}

Unity3D - how to use arrays with custom inspector code?

I seem to be stuck in a catch 22 situation with the OnInspectorGUI method of Unity's UnityEditor class. I want to name array elements in the inspector for easy editing, currently I'm using, as per the documentation:
public override void OnInspectorGUI()
{
J_Character charScript = (J_Character)target;
charScript.aBaseStats[0] = EditorGUILayout.FloatField("Base Health", charScript.aBaseStats[0]);
}
In my J_Character script I initialise the aBaseStats array like so:
public float[] aBaseStats = new float[35];
The problem is that whenever I try to do anything in the editor (and thus OnInspectorGUI is called) I get an index out of range error pointing to the line
charScript.aBaseStats[0] = EditorGUILayout.FloatField("Base Health", charScript.aBaseStats[0]);
I'm guessing this is because my array is initialized on game start while the editor code is running all the time while developing.
How can I get round this situation?
Many thanks.
You have to initialize aBaseStats in an function that runs only once.
The code below is BAD:
public float[] aBaseStats = new float[35];
void Start(){
}
The code below is GOOD:
public float[] aBaseStats;
void Start(){
aBaseStats = new float[35];
}
Initialize it in an Editor callback function that runs once.
EDIT:
I don't know a Start callback function that will run before the OnInspectorGUI function(). The hack below should work.
public float[] aBaseStats;
bool initialized = false;
public override void OnInspectorGUI()
{
if (!initialized)
{
initialized = true;
aBaseStats = new float[35];
}
J_Character charScript = (J_Character)target;
charScript.aBaseStats[0] = EditorGUILayout.FloatField("Base Health",aBaseStats[0]);
}
As an addition to the answer by Programmer I would like to point you to the following:
http://docs.unity3d.com/ScriptReference/ExecuteInEditMode.html
This seems to be exactly what you are looking for in terms of functionality. (it runs the method even when playmode is not active)
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class ExampleClass : MonoBehaviour {
public Transform target;
void Update() {
if (target)
transform.LookAt(target);
}
}

Interlocked.Increment not working with my Get variable name

I have WPF application and my work method play my files in different threads
This is my Global variable that update my UI:
public static int _totalFilesSent;
Now because i am implement INotifyPropertyChanged in my model i have also this:
public static int TotalFilesSent
{
get { return _totalFilesSent; }
set
{
_totalFilesSent = value;
OnStaticlPropertyChanged("TotalFilesSent");
}
}
(i didn't add the event function because this is not relevant here).
So every time i am update my Global variable this way:
Interlocked.Increment(ref _totalFilesSent );
Now because i need to update my UI with my INotifyPropertyChanged event i need to use TotalFilesSent instead of _totalFilesSent but in this way i got this compilation error:
A property, indexer or dynamic member access may not be passed as an
out or ref parameter.
What does it mean and how can i solved it ?
You may easily raise the StaticPropertyChanged event after calling Interlocked.Increment:
private static int _totalFilesSent;
public static int TotalFilesSent
{
get { return _totalFilesSent; }
}
public static void IncrementTotalFilesSent()
{
Interlocked.Increment(ref _totalFilesSent);
OnStaticPropertyChanged("TotalFilesSent");
}

How to properly canalize multithreaded message flow in a single threaded service?

In a WPF application, I have a 3rd party library that is publishing messages.
The messages are like :
public class DialectMessage
{
public string PathAndQuery { get; private set; }
public byte[] Body { get; private set; }
public DialectMessage(string pathAndQuery, byte[] body)
{
this.PathAndQuery = pathAndQuery;
this.Body = body;
}
}
And I setup the external message source from my app.cs file :
public partial class App : Application
{
static App()
{
MyComponent.MessageReceived += MessageReceived;
MyComponent.Start();
}
private static void MessageReceived(Message message)
{
//handle message
}
}
These messages can be publishing from multiple thread at a time, making possible to call the event handler multiple times at once.
I have a service object that have to parse the incoming messages. This service implements the following interface :
internal interface IDialectService
{
void Parse(Message message);
}
And I have a default static instance in my app.cs file :
private readonly static IDialectService g_DialectService = new DialectService();
In order to simplify the code of the parser, I would like to ensure only one message at a time is parsed.
I also want to avoid locking in my event handler, as I don't want to block the 3rd party object.
Because of this requirements, I cannot directly call g_DialectService.Parse from my message event handler
What is the correct way to ensure this single threaded execution?
My first though is to wrap my parsing operations in a Produce/Consumer pattern. In order to reach this goal, I've try the following :
Declare a BlockingCollection in my app.cs :
private readonly static BlockingCollection<Message> g_ParseOperations = new BlockingCollection<Message>();
Change the body of my event handler to add an operation :
private static void MessageReceived(Message message)
{
g_ParseOperations.Add(message);
}
Create a new thread that pump the collection from my app constructor :
static App()
{
MyComponent.MessageReceived += MessageReceived;
MyComponent.Start();
Task.Factory.StartNew(() =>
{
Message message;
while (g_ParseOperations.TryTake(out message))
{
g_DialectService.Parse(message);
}
});
}
However, this code does not seems to work. The service Parse method is never called.
Moreover, I'm not sure if this pattern will allow me to properly shutdown the application.
What have I to change in my code to ensure everything is working?
PS: I'm targeting .Net 4.5
[Edit] After some search, and the answer of ken2k, i can see that I was wrongly calling trytake in place of take.
My updated code is now :
private readonly static CancellationTokenSource g_ShutdownToken = new CancellationTokenSource();
private static void MessageReceived(Message message)
{
g_ParseOperations.Add(message, g_ShutdownToken.Token);
}
static App()
{
MyComponent.MessageReceived += MessageReceived;
MyComponent.Start();
Task.Factory.StartNew(() =>
{
while (!g_ShutdownToken.IsCancellationRequested)
{
var message = g_ParseOperations.Take(g_ShutdownToken.Token);
g_DialectService.Parse(message);
}
});
}
protected override void OnExit(ExitEventArgs e)
{
g_ShutdownToken.Cancel();
base.OnExit(e);
}
This code acts as expected. Messages are processed in the correct order. However, as soon I exit the application, I get a "CancelledException" on the Take method, even if I just test the IsCancellationRequested right before.
The documentation says about BlockingCollection.TryTake(out T item):
If the collection is empty, this method immediately returns false.
So basically your loop exits immediately. What you may want is to call the TryTake method with a timeout parameter instead, and exit your loop when a mustStop variable becomes true:
bool mustStop = false; // Must be set to true on somewhere else when you exit your program
...
while (!mustStop)
{
Message yourMessage;
// Waits 500ms if there's nothing in the collection. Avoid to consume 100% CPU
// for nothing in the while loop when the collection is empty.
if (yourCollection.TryTake(out yourMessage, 500))
{
// Parses yourMessage here
}
}
For your edited question: if you mean you received a OperationCanceledException, that's OK, it's exactly how methods that take a CancellationToken object as parameter must behave :) Just catch the exception and exit gracefully.

Cleanest way to implement a delayed action on UI thread

I have an action I need to perform around 3 seconds after my app starts. I've implemented it as follows:
internal static class Entry
{
private static SplashScreen splashScreen;
[STAThread]
internal static void Main()
{
ShowSplashScreen();
StartApp();
}
private static void ShowSplashScreen()
{
splashScreen = new SplashScreen("Splash.png");
splashScreen.Show(false, true);
}
private static void StartApp()
{
var app = new App();
//this, in particular, is ugly and more difficult to comprehend than I'd like
var dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
dispatcherTimer.Tick += delegate
{
CloseSplashScreen();
dispatcherTimer.Stop();
};
dispatcherTimer.Start();
app.Run();
}
private static void CloseSplashScreen()
{
splashScreen.Close(TimeSpan.FromSeconds(1));
}
}
I find the StartApp() code rather ugly but have not been able to concoct a neater alternative. Is there a common idiom I'm missing here?
PS. Yes, I'm aware SplashScreen has an auto-close option. I'm not wanting to use that mainly because it begins closing as soon as the app has loaded, which I don't want to do.
Here is something similar you might be interested in:
How do we do idle time processing in WPF application?
It's not exactly what you are looking for, because it will close your window as soon as your app goes idle, but you might consider to start your delay after your app went idle. You might find that link helpful than.
Do you not have a specific state when your application is done starting? Normally you want your SplashScreen to close when your application is ready to handle user input, instead of an arbitrary 3 secs. So I would suggest to close your SplashScreen then.
This is about the best I could come up with:
internal static class Entry
{
private static SplashScreen splashScreen;
private static App app;
[STAThread]
internal static void Main()
{
ShowSplashScreen();
CreateApp();
PumpDispatcherUntilPriority(DispatcherPriority.Loaded);
PumpDispatcherFor(TimeSpan.FromSeconds(2));
CloseSplashScreen();
PumpDispatcherUntilAppExit();
}
private static void ShowSplashScreen()
{
splashScreen = new SplashScreen("Splash.png");
splashScreen.Show(false, true);
}
private static void CloseSplashScreen()
{
splashScreen.Close(TimeSpan.FromSeconds(0.5));
}
private static void CreateApp()
{
app = new App();
}
private static void PumpDispatcherUntilPriority(DispatcherPriority dispatcherPriority)
{
var dispatcherFrame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke((ThreadStart)(() => dispatcherFrame.Continue = false), dispatcherPriority);
Dispatcher.PushFrame(dispatcherFrame);
}
private static void PumpDispatcherFor(TimeSpan timeSpan)
{
var dispatcherFrame = new DispatcherFrame();
using (var timer = new Timer(o => dispatcherFrame.Continue = false, null, (long)timeSpan.TotalMilliseconds, Timeout.Infinite))
{
Dispatcher.PushFrame(dispatcherFrame);
}
}
private static void PumpDispatcherUntilAppExit()
{
var dispatcherFrame = new DispatcherFrame();
app.Exit += delegate
{
dispatcherFrame.Continue = false;
};
Dispatcher.PushFrame(dispatcherFrame);
}
}
I toyed with extension methods for Dispatcher, but ultimately found them less intuitive. That's because PushFrame() is static, so any extension methods don't actually execute against the Dispatcher they're invoked against. YMMV.
Note that you could also call app.Run() instead of PumpDispatcherUntilAppExit(), but I just did that for consistency.
Does not really matter if it is ugly, you can just refactor it into a method which takes an Action as parameter for example and that won't be much of a problem.
As by ugly you probably meant that it looks like bad code i would suggest the use of a normal thread (with Thread.Sleep before your action) which uses Dispatcher.Invoke instead. I for one am not aware of any best practice regarding this though. This can also be nicely refactored into a simple method taking an Action.
If you want a non-blocking wait there is a question to be found about that as well.

Resources