Here is what i want to do
// pseudo code
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 myForm = new Form1();
Application.Run(myForm);
while(true)
{
string a = readline();
}
form1.show(a)
In other words , I need the form always show the input. but the code above will stop after 'Application.Run(myForm);'. The reason I don't write such code in the form1 class is the main part of code is run on a machine learning engine written in F#, and because F# doesn't have a good visual designer. So I am trying to create a simple form1.dll, and use it to plot the result over time.
So my problem is I only can initialise the form, but I can't update it over time.
Any hints will be appreciated.
You're trying to do 2 things at the same time, so your application should reflect that by using 2 threads. Next, the Form's Show() method does not accept a string, so you need to implement your own method.
Here's a C# 2.0 WinForms solution. The program runs the thread and processes the console input:
static class Program
{
[STAThread]
private static void Main()
{
// Run form in separate thread
var runner = new FormRunner();
var thread = new Thread(runner.Start) {IsBackground = false};
thread.Start();
// Process console input
while (true)
{
string a = Console.ReadLine();
runner.Display(a);
if (a.Equals("exit")) break;
}
runner.Stop();
}
}
The FormRunner takes care about thread invocation:
internal class FormRunner
{
internal Form1 form = new Form1();
internal void Start()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(form);
}
private delegate void StopDelegate();
public void Stop()
{
if (form.InvokeRequired)
{
form.Invoke(new StopDelegate(Stop));
return;
}
form.Close();
}
private delegate void DisplayDelegate(string s);
public void Display(string s)
{
if (form.InvokeRequired)
{
form.Invoke(new DisplayDelegate(form.Display), new[] {s});
}
}
}
And Form1 just needs something to display:
public void Display(string s)
{
textBox1.Multiline = true;
textBox1.Text += s;
textBox1.Text += Environment.NewLine;
}
Related
Program.cs
namespace PerformanceMonitor
{
static class Program
{
private static int NumberOfCores;
private static List<int> CPULoadVals;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MonitorGUI());
NumberOfCores = getNumberOfCores();
CPULoadVals = getCoreLoadVals();
}
private static int getNumberOfCores()
{
int coreCount = 0;
foreach (var core in new ManagementObjectSearcher("SELECT * FROM Win32_Processor").Get())
{
coreCount += int.Parse(core["NumberOfCores"].ToString());
}
return coreCount;
}
...
MonitorGUI.cs
namespace PerformanceMonitor
{
public partial class MonitorGUI : Form
{
public static List<Label> labels;
private static List<int> CPULoadVals;
public MonitorGUI()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
...
}
Debugging the app I can see that InitializeComponent() is invoked causing a new form to be created (Application.Run(new MonitorGUI());) but trying to step through after that and nothing is called. The method on form load is not even called even though I can visually see that it's loaded
Application.Run()
Begins running a standard application message loop on the current thread, and makes the specified form visible.
This method blocks and only returns when you close the Form passed as argument. So all calls after that are executed when you close your main window.
You might want to change the order:
[STAThread]
static void Main()
{
NumberOfCores = getNumberOfCores();
CPULoadVals = getCoreLoadVals();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MonitorGUI());
}
And Form1_Load() is only called if you subscribed to the Load event of the Form:
public MonitorGUI()
{
InitializeComponent();
Load += Form1_Load; // <--- subscribe to the event
}
But this can also be done in designer. Check if you have set this event correctly.
i have a console application that starts a windows form in a separate thread like this :
static void Main(string[] args)
{
Thread t = new Thread(StartForm);
t.Start();
}
static public void StartForm()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
Form Conatains Richtextbox Control .
My question : How do i write Text to the Richtextbox control in the form from my application (and from anyThread)?
PS: i also Need the Console to stay.
You can use Invoke to write text to RichTextBox from background thread.
In Form1 designer, change richTextBox1.Modifiers to public, in order to access it form other thread.
static void Main(string[] args)
{
Thread t = new Thread(StartForm);
t.Start();
string text = Console.ReadLine();
form.UIThread(() => form.richTextBox1.Text += text);
Console.ReadLine();
}
public static Form1 form;
public static void StartForm()
{
form = new Form1();
Application.EnableVisualStyles();
Application.Run(form);
}
public static void UIThread(this Control control, Action action)
{
if (control.InvokeRequired) // You're access from other thread
{
control.BeginInvoke(action); // Invoke to access UI element
}
else
{
action.Invoke();
}
}
You need to use Invoke or BeginInvoke if you want to update your form's content from another thread. You can check whether or not you need to do so by checking the InvokeRequired property. While you can pass any Delegate, you should pass a MethodInvoker delegate, which is a special delegate made for use with Windows Forms.
For example:
if(form.TheRichTextBox.InvokeRequired)
{
form.TheRichTextBox.Invoke(new MethodInvoker(() =>
{
form.TheRichTextBox.Text += "I had to be invoked!";
}));
}
else
{
form.TheRichTextBox.Text += "I didn't have to be invoked!";
}
I'm new at C# programming and i'm lost with a thing that could be simple.
Executing a console application, at a moment i need to call a Windows Form that will show statics of the execution but when i call the form1.ShowDialog(); this stop the console runtime.
How do i keep my console execution alive while i show a Windows form screen ?
class Program
{
static Form1 form = new Form1();
public static bool run = true;
static void Main(string[] args)
{
work();
}
public static void work()
{
form.Show();
while (run)
{
Console.WriteLine("Console still running");
}
}
}
try this it work on me
using System.Windows.Forms;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
public static bool run = true;
static void Main(string[] args)
{
Startthread();
Application.Run(new Form1());
Console.ReadLine();
}
private static void Startthread()
{
var thread = new Thread(() =>
{
while (run)
{
Console.WriteLine("console is running...");
Thread.Sleep(1000);
}
});
thread.Start();
}
}
}
Threading is like "process inside a process" in my own understanding.
See this question. You have to use Form1.Show() because Form1.ShowDialog() pauses execution until the form is closed.
Update This seems to be working (with Application.Run):-
public static Form1 form = new Form1();
public static bool run = true;
[MTAThread]
static void Main(string[] args)
{
new Thread(() => Application.Run(form)).Start();
new Thread(work).Start();
}
public static void work()
{
while (run)
{
Console.WriteLine("Console Running");
}
}
I have the following C# code:
using System;
using System.Windows.Forms;
namespace WinFormErrorExample
{
public partial class Form1 : Form
{
public static Form1 Instance;
public Form1()
{
Instance = this;
InitializeComponent();
}
public void ChangeLabel1Text(String msg)
{
if (InvokeRequired)
Invoke(new Action<String>(m => label1.Text = m), new object[] {msg});
else
label1.Text = msg;
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Instance.ChangeLabel1Text("cool");
}
}
}
}
When i'm calling the Instance.ChangeLabel1Text("cool"); nothing is happening in the GUI.
This is a small program i constructed to show my problem in a larger program.
Why is the GUI not being updated?
The call to
Application.Run(new Form1());
is blocking your application until the Form1 closes. So your subsequent line is not executed until you try to close
Of course, if you just want to test the functionality of the Instance call then remove that line after the Application.Run. Instead you need to create a separate thread that tries to call that method on the Form1 current instance
The Application.Run(new Form1()); method call performs running a standard application message loop on the current thread. So, this line Instance.ChangeLabel1Text("cool"); will be executed when the application is closed.
Why not change the text of the label inside the constructor? No static variables needed.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ChangeLabel1Text("Hello!");
}
}
This would do,
First set the text to textbox control and then Run()
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 form = new Form1();
form.Controls["ChangeLabel1Text"].Text = "cool";
Application.Run(form);
I was wondering if someone could help me with a little issue I'm having. I'm trying to update a textbox from another class but the text is not showing up on in the textbox even though it is being sent as I have printed it to the screen.
The code I'm using is below:
Program.cs
namespace Search
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
try
{
Application.SetCompatibleTextRenderingDefault(false);
}
catch (InvalidOperationException e)
{
}
Application.Run(new Form1());
}
public static readonly Form1 MainLogWindow = new Form1();
}
}
HexToASCII:
public class HexToASCII
{
Output o = new Output();
public void hexToAscii(String hex, int textBox)
{
//Convert the string of HEX to ASCII
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hex.Length; i += 2)
{
string hs = hex.Substring(i, 2);
sb.Append(Convert.ToChar(Convert.ToUInt32(hs, 16)));
}
//Pass the string to be output
string convertedHex = sb.ToString();
Program.MainLogWindow.UpdateTextBox(convertedHex);
}
}
Form1:
private delegate void NameCallBack(string varText);
public void UpdateTextBox(string input)
{
if (InvokeRequired)
{
textBox2.BeginInvoke(new NameCallBack(UpdateTextBox), new object[] { input });
}
else
{
textBox2.Text = textBox2.Text + Environment.NewLine + input;
}
}
I have tried to run it using a new thread ThreadStart ts = delegate()... but I'm unable to get the textbox to update. Sorry I'm very new to c#, could someone please explain the issue so I can understand it and learn for next time. Many thanks :)
This is the problem:
static void Main()
{
...
Application.Run(new Form1());
}
public static readonly Form1 MainLogWindow = new Form1();
You're creating two forms: one of them is being shown (with Application.Run) but you're changing the contents of the text box on the other one:
Program.MainLogWindow.UpdateTextBox(convertedHex);
You haven't shown how you're calling hexToAscii in the first place - personally I would try to avoid having static references to GUI elements like this, but you could get your code to work just by changing your Main method to use:
Application.Run(MainLogWindow);