public static void Monitor0()
{
bool ToMineOrNot = Backend.ToMineOrNot;
while (ToMineOrNot)
{
Form1 temp = new Form1();
Form1.NonStaticDelegate = new Action(temp.setHashRate);
Form1.NonStaticDelegate();
Backend.hps = 0;
Thread.Sleep(1000);
}
if (ToMineOrNot == false)
{
}
}
public void setHashRate()
{
hashrate.Text = Backend.hps.ToString();
}
I have to get the Static Void to call the non Static Void, i have to have Monitor0 Static because it has to be Run in a Thread, and setHashRate() has to be Non-static to edit the label (It's a Windows form):
Thread thread = new Thread(Monitor0);
thread.Start();
Does anybody know how i could Do that? and I cant just do this because the label won't be changed:
Form1 form = new Form();
form.label1.Text = "text"
Related
I'm trying to make a simple clock program with threads. In Form1 I want to create a new thread that's in ThreadProc(), take time, and sent back to Form1 send() method that will replace the text in label.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ThreadProc tP = new ThreadProc();
Thread t = new Thread(tP.threadP);
t.Start();
}
public void send(Object obj)
{
string time;
try
{
time = (string)obj;
}
catch (InvalidCastException)
{
time = " ";
}
if (label1.InvokeRequired)
this.Invoke((MethodInvoker)delegate () { label1.Text = time; });
else
label1.Text = time;
}
}
internal class ThreadProc
{
public void threadP()
{
Form1 form1 = new Form1();
DateTime dateTime;
do
{
dateTime = DateTime.Now;
string time = dateTime.ToString();
Thread t = new Thread(() => form1.send(time));
t.Start();
Thread.Sleep(500);
} while (true);
}
}
It ends up in infinite loop of Form1() -> threadP() -> Form1()... but without
Form1 form1 = new Form1();
I can't call send() in
Thread t = new Thread(() => form1.send(time));
The threadP() has to be in their own class and send() has to be in Form1 class.
Pass a reference to your form to the thread. You can then access it from there.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ThreadProc tP = new ThreadProc();
Thread t = new Thread(tP.threadP);
// Automatically end thread when application ends
t.IsBackground = true;
// Pass reference to this form to thread
t.Start(this);
}
public void Send(string time)
{
if (Visible) // Check form wasn't closed
{
if (label1.InvokeRequired)
this.Invoke((MethodInvoker)delegate () { label1.Text = time; });
else
label1.Text = time;
}
}
}
internal class ThreadProc
{
public void threadP(object data)
{
// Get Form1 reference from start parameter
Form1 form1 = data as Form1;
DateTime dateTime;
do
{
dateTime = DateTime.Now;
string time = dateTime.ToString();
form1.Send(time);
Thread.Sleep(500);
} while (true);
}
}
Note that there are better designs to re-use the thread like passing an interface instead of the concrete Form1 class. But this is just a simple example.
When a Form and a background thread are so closely bound together, you usually use a BackgroundWorker instead of threads.
I have a problem with using nancyfx in my winform application (I make a winform app and use a nancyfx inside the application) So i can use some API url to make change in the winform without additional server or services (because i attached the nancy in the winform apps)
Here is my Form1.cs
public partial class Form1 : Form
{
public Form1(bool test)
{
InitializeComponent();
textBox1.Text += "Apps Method "+ Environment.NewLine;
}
public bool startTestAPI()
{
textBox1.Text += "Api Worked" + Environment.NewLine);
}
private void button2_Click(object sender, EventArgs e)
{
HostingAPI s = new HostingAPI();
s.Start();
textBox1.Text += "Api Running" + Environment.NewLine);
}
}
public class ModuleCDM : NancyModule
{
public ModuleCDM()
{
try
{
Thread th2 = Thread.CurrentThread;
Get["/Start"] = parameters =>
{
Form1 form = new Form1(false);
Thread testthread = Form1.curthread;
bool res = form.startTestAPI();
if (res == true)
{
var feeds = new string[] { "Success" };
return Response.AsJson(feeds);
}
else
{
var feeds = new string[] { "Failed" };
return Response.AsJson(feeds);
}
};
}
}
}
and this is my HostingAPI.cs
public class HostingAPI
{
private NancyHost hostNancy;
private string hostUrl;
public void Start()
{
hostUrl = ConfigModule.ModuleAddress;
if (hostUrl == null) hostUrl = "http://localhost:5005";
hostNancy = new NancyHost(new Uri(hostUrl));
hostNancy.Start();
}
public void Stop()
{
hostNancy.Stop();
}
}
And it successfully run without error, but when i call api (localhost:5005/Start) the textbox in winform apps not add the text i wanted ("Api Worked"). I noticed it is because Nancyfx create another thread when there is API call, and i can use invoke/begininvoke because !invokerequired always comes with value false. So how can i access the main thread or maybe another solution to update the UI when i call the API.
Thanks
You have 2 issues in here.
You start host api service from Form1 instance then within Nancy Module you create a different Form1 instance which is invisible and you try to do access certain methods within that class
Cross thread issue as you rightfully guessed . You are trying to write from another thread context than the UI thread
Look at the code at below to achieve this. Bear in mind that you can create Singleton Form or find another way to access the instance of Form1
public class HostingAPI
{
private NancyHost hostNancy;
private string hostUrl;
public HostingAPI()
{
}
public void Start()
{
var hostConfig = new HostConfiguration
{
UrlReservations = new UrlReservations
{
CreateAutomatically = true
},
};
//hostUrl = ConfigModule.ModuleAddress;
if (hostUrl == null) hostUrl = "http://localhost:5005";
hostNancy = new NancyHost(hostConfig,new Uri(hostUrl));
hostNancy.Start();
}
public void Stop()
{
hostNancy.Stop();
}
}
public partial class Form1 : Form
{
delegate void SetTextCallback(string text);
public static Form1 Instance;
public Form1(bool test)
{
InitializeComponent();
textBox1.Text += "Apps Method " + Environment.NewLine;
Instance = this;
}
private void button1_Click(object sender, EventArgs e)
{
HostingAPI s = new HostingAPI();
s.Start();
textBox1.Text += "Api Running" + Environment.NewLine;
}
public void startTestAPI()
{
SetText("Api Worked" + Environment.NewLine);
}
private void SetText(string text)
{
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text += text;
}
}
}
public class ModuleCDM : NancyModule
{
public ModuleCDM()
{
try
{
Thread th2 = Thread.CurrentThread;
Get["/Start"] = parameters =>
{
var form1 = Form1.Instance;
form1.startTestAPI();
var feeds = new[] {"Success"};
return Response.AsJson(feeds);
};
}
catch
{
}
}
}
I've found that example (Communicate between two windows forms in C#) that works fine but not when the two forms are in different thread.
I've got an "System.NullReferenceException" at line 20 in MainForm (this.splashy.LabelText = i;)
The point of this script is to modified the width of the progressBar in the splashscreen when MainForm is doing his job.
Thanks in advance!
Here are the two c# classes and program file:
//Program.cs
using System;
using System.Threading;
using System.Windows.Forms;
namespace GIS
{
static class Program
{
public static SplashScreen splashy = null;
/// <summary>
/// Point d'entrée principal de l'application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread splashThread = new Thread(new ThreadStart(
delegate
{
//SplashScreen splashy = new SplashScreen();
splashy = new SplashScreen();
Application.Run(splashy);
}
));
splashThread.SetApartmentState(ApartmentState.STA);
splashThread.Start();
//run form - time taking operation
MainForm mainForm = new MainForm(splashy);
mainForm.Load += new EventHandler(mainForm_Load);
Application.Run(mainForm);
}
static void mainForm_Load(object sender, EventArgs e)
{
//close splash
if (splashy == null)
{
return;
}
splashy.Invoke(new Action(splashy.Close));
splashy.Dispose();
splashy = null;
}
}
}
//SplashScreen.cs
using System;
using System.Windows.Forms;
namespace GIS
{
public partial class SplashScreen : Form
{
public SplashScreen()
{
InitializeComponent();
}
public int LabelText
{
get
{
return rectangleShape1.Width;
}
set
{
rectangleShape1.Width = value;
}
}
}
}
//MainForm.cs
using System.Threading;
using System.Windows.Forms;
namespace GIS
{
public partial class MainForm : Form
{
private SplashScreen splashy = null;
public MainForm(Form callingForm)
{
splashy = callingForm as SplashScreen;
InitializeComponent();
doWork();
}
private void doWork()
{
for(int i = 0; i < 100; i++)
{
this.splashy.LabelText = i;
Thread.Sleep(10);
}
}
}
}
You need to invoke the SplashScreen to change it's value from an other thread like
this.splashy.Invoke((MethodInvoker) delegate { this.splashy.LabelText = "Requested" + repeats + "Times"; });
Note that the constructor
splashy = callingForm as SplashScreen;
allows splashy to be null - this causes your current NullReferenceException.
This problem is locaed in this snipped:
Thread splashThread = new Thread(new ThreadStart(
delegate
{
splashy = new SplashScreen();
Application.Run(splashy);
}
));
splashThread.SetApartmentState(ApartmentState.STA);
splashThread.Start();
//run form - time taking operation
MainForm mainForm = new MainForm(splashy);
The new thread you are start is not fast enought to create the instance of SplashScreen before you pass it. The result - you are passing null.
Fix it by create the splashy before your thread starts:
splashy = new SplashScreen();
Thread splashThread = new Thread(new ThreadStart(
delegate
{
Application.Run(splashy);
}
I have some trouble accessing the ProgressBar and a certain Label in from my splashScreen. I made an own Form for the screen. In my Form1 I have the following method:
private void sign_Click(object sender, EventArgs e)
{
splashScreen splScreen = new splashScreen();
Thread thrd = new Thread(new ThreadStart(loadingScreenStart));
thrd.Start();
splScreen.percentage.Text = "0%";
var logIn = new LogIn(this);
logIn.checkUserInput(this);
thrd.Abort();
}
public void loadingScreenStart()
{
Application.Run(new splashScreen());
}
In my LogIn class I did:
public String checkUserInput(object sender)
{
splashScreen splScreen = new splashScreen();
//won't change my Label and PrpgressBar
I know it's probably because I create a new instance of the Form so it's empty but how to do this right? I don't know... Hope someone can help me.
Same requirement I too had where I need to use the same object but was having a limitation where i cannot use the static class. For that i have created a static object of the class and using lock. Try if it solves your requirement.
private static splashScreen m_instance = null;
private static object m_instanceLock = new object();
public static splashScreen GetInstance()
{
lock (m_instanceLock)
{
if (m_instance == null)
{
m_instance = new splashScreen();
}
}
return m_instance;
}
And whenever you want to create the object or access the already created object, you just need to give as:
SomeClass someobj= SomeClass.GetInstance();
Hi I have a use case where I am supposed to use C# Web Browser inside a form and get some data from it. However as we know the C# browser runs under STA hence I have created an instance of SmartThread with single thread architecture.
On some events from an MVC app I am supposed to invoke the web browser and get the result. When the browser is instantiated at that moment I can invoke any JavaScript method, however when I wait for an event in MVC and invoke on event the SmartThread doesn't seems to invoke the webbrowser.
Here is my below code please help me.
public class FormBrowser
{
public static Form1 form1 = null;
public static SmartThreadPool smartThreadPool;
public static void initialise()
{
if (smartThreadPool == null)
{
STPStartInfo stpStartInfo = new STPStartInfo();
stpStartInfo.StartSuspended = true;
stpStartInfo.ApartmentState = ApartmentState.STA;
stpStartInfo.MaxWorkerThreads = 1;
smartThreadPool = new SmartThreadPool(stpStartInfo);
var ab = smartThreadPool.QueueWorkItem(new WorkItemCallback(initForm), "line");
smartThreadPool.Start();
//smartThreadPool.Shutdown();
}
}
public static object initForm(object msg)
{
var id = Thread.CurrentThread.ManagedThreadId;
form1 = new Form1();
System.Windows.Forms.Application.Run(form1);
return null;
}
public static void redraw()
{
var id = Thread.CurrentThread.ManagedThreadId;
smartThreadPool.QueueWorkItem(new WorkItemCallback(rd), "line");
}
public static object rd(object msg)
{
var id = Thread.CurrentThread.ManagedThreadId;
form1.webBrowser1.Document.InvokeScript("startDrawing");
return null;
}
}
On calling initialise() method SmartThread will create a thread pool and then creates a Form instance which holds a Web Browser. Next when any event occures from client say he request for a latest data I have to call method redraw() and which should internally call rd() but that never happens.
Please help me to fix this, if I am missing something let me know.
The below code worked for me.
public class FormBrowser
{
public static Form1 form1 = null;
public static SmartThreadPool smartThreadPool;
public static SynchronizationContext ctx;
public static string html;
public static void initialise()
{
if (smartThreadPool == null)
{
STPStartInfo stpStartInfo = new STPStartInfo();
stpStartInfo.StartSuspended = false;
stpStartInfo.ApartmentState = ApartmentState.STA;
stpStartInfo.MaxWorkerThreads = 1;
smartThreadPool = new SmartThreadPool(stpStartInfo);
var ab = smartThreadPool.QueueWorkItem(new WorkItemCallback(initForm), "line");
smartThreadPool.Start();
//smartThreadPool.Shutdown();
}
}
public static object initForm(object msg)
{
var id = Thread.CurrentThread.ManagedThreadId;
form1 = new Form1();
ctx = WindowsFormsSynchronizationContext.Current;
System.Windows.Forms.Application.Run(form1);
return null;
}
public static string redraw(string chartType)
{
ctx.Send(rd, chartType);
return html;
}
public static void rd(object chartType)
{
var id = Thread.CurrentThread.ManagedThreadId;
html = (string)form1.webBrowser1.Document.InvokeScript("drawChart", new object[] { chartType });
}
}
If SmartThreadPool used along with the SynchronizationContext works well. However using SynchronizationContext alone or SmartThreadPool alone won't solve the issue.