Windows Form starten en updaten vanuit Console App

Status
Niet open voor verdere reacties.

DMK

Gebruiker
Lid geworden
5 nov 2013
Berichten
31
Hallo,

Ik wil graag vanuit een Console applicatie een windows Form starten en gedurende de hele tijd dit form kunnen updaten.
Ik weet al dat ik moet werken met meerdere threads maar kom er niet uit om het werkend te krijgen.

Als ik een nieuw form aanmaak (ui.ShowDialog()), dan doet stopt hij met uitvoeren van de code totdat ik het form sluit, terwijl ik dit net niet wil.

Weet iemand een oplossing?

Bedankt


Dit heb ik tot nu toe:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UserInterface
{
    class Program
    {
        class Class2
        {
            UserInterface ui = new UserInterface();
            [STAThread]
            static void Main()
            {
                Class2 t = new Class2();
                t.createForm();
                t.test();
            }

            private void createForm()
            {
                ui.ShowDialog();
            }
            
            public void test()
            {
                Thread t = new Thread(new ThreadStart(StartNewStaThrea));
                t.Start();
            }

            private void StartNewStaThrea()
            {
                ui.toonAlles();
            }

        }
    }
}

Edit, heb ook het volgende geprobeerd maar ook hierbij lukt het niet:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UserInterface
{
    class Program
    {
        class Class2
        {
            UserInterface ui = new UserInterface();
            int i;
            [STAThread]
            static void Main()
            {
                Control.CheckForIllegalCrossThreadCalls = false;
                Class2 t = new Class2();
                t.test();
            }

            public void test()
            {
                Task task1 = Task.Factory.StartNew(() => StartNewStaThrea1());
                Task task2 = Task.Factory.StartNew(() => StartNewStaThrea2());
                Task.WaitAll(task1, task2);
                ui.ShowDialog();
                Console.ReadKey();
            }

            private void StartNewStaThrea1()
            {
                i = 0;
                while (i < 20000)
                {
                    ui.toonHuidig(i);
                    i++;
                }
            }

            private void StartNewStaThrea2()
            {
                if (i == 10000)
                {
                    ui.update();
                }
            }
        }
    }
}
 
Laatst bewerkt:
Dan gebeurt precies hetzelfde alleen krijg ik dan over mijn complete form een windows laadcursor te zien en hangt alles vast (totdat ik sluit)
 
Misschien helpt dit je verder. Zo kun je beide gebruiken.


Code:
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Setting up UI");

            var uiThread = new Thread(RunUI);
            uiThread.Start();

            Console.WriteLine("UI Loaded");
            Console.ReadLine();
        }

        static void RunUI()
        {

            var uiController = new UIController();
            Application.Run(uiController.MainForm);

        }

    }

    class UIController
    {
        public Form MainForm { get; set; }

        public UIController()
        {
            MainForm = new Form();
            MainForm.Text = "Main Window";

            var btnClose = new Button() { Text = "Close" };
            btnClose.Click += (s, e) => MainForm.Close();

            MainForm.Controls.Add(btnClose);
        }
    }
 
Bedankt,

Heb het een klein beetje aangepast zodat ik het windows Form (UserInterface.cs) aanroep ipv handmatig een form ga programmeren.
Dit werkt, alleen zou ik graag overal in deze code het form willen kunnen updaten.

Hoe moet ik dit dan aanpassen?


Het for loopje is puur om te testen of het op de achtergrond doorloopt. Ik wil ook om te testen in het forloopje een methode aanroepen uit de classe UserInterface (form) die een tekstveld update


Wat ik dus uiteindelijk wil bereiken:
Ik heb een classe ProcesManager. Dit is alle intelligentie van het programma. (dit is de main, deze stuurt alles aan). Tijdens het uitvoeren van de code moet vanuit de ProcesManager alles aangestuurd worden (zo ook het form).

De ProcesManager moet dus op elke plek een methode op de UserInterface kunnen aanroepen.
Hoop dat het nu wat duidelijke is wat ik wil?

Misschien dat iemand me hiermee kan helpen?
Bedankt!


Code:
    class Program
    {        
        static void Main(string[] args)
        {
            Console.WriteLine("Setting up UI");

            var uiThread = new Thread(RunUI);
            uiThread.Start();
            for (int i = 0; i < 1000000; i++)
            {
                
                Console.WriteLine(i);
            }

            Console.WriteLine("UI Loaded");
            Console.ReadLine();
        }

        static void RunUI()
        {
            var uiController = new UIController();
            Application.Run(uiController.MainForm);

        }

    }

    class UIController
    {
        public Form MainForm { get; set; }

        public UIController()
        {
            MainForm = new UserInterface();
            
        }
    }
 
Laatst bewerkt:
Zal ongeveer hetzelfde zijn, hier is een voorbeeld dat alles wat je in console window typt in een listbox zet. Via de process controller.

Code:
class Program
{
	private static ProcessManager _manager;

	static void Main(string[] args)
	{
		Console.WriteLine("Initializing...");
		new Thread(Run).Start();

		Console.WriteLine("Initializing Complete. Enter any message you want to send to the main window.");

		//quick test code, adds line to listbox in window
		var val = Console.ReadLine();
		while (val != "exit")
		{
			_manager.Log(val);
			val = Console.ReadLine();
		}

		Application.Exit();
	}

	static void Run()
	{
		_manager = new ProcessManager(new MainView());
		_manager.Start();
	}
}

Code:
public class ProcessManager
{
	private readonly MainView _mainView;

	public ProcessManager(MainView mainView)
	{
		_mainView = mainView;
	}

	public MainView MainView
	{
		get { return _mainView; }
	}

	public void Start()
	{
		Application.Run(_mainView);
	}

	public void Log(string message)
	{
		_mainView.LogMessage(message);
	}
}

een voorbeeld method in form (thread invoke)
Code:
public void LogMessage(string message)
{
	if (listBox1.InvokeRequired)
		listBox1.Invoke(new Action<string>(LogMessage), new object[] {message});
	else
		listBox1.Items.Add(message);
}

25i3cio.png
 
Super!!!
Tot zover precies wat ik nodig heb ;)
 
Heb toch nog een probleempje. Je voorbeeld werkt, maar alle code die ik zelf maak (dingen tekenen op het form enzo), krijg ik de melding: Cross-thread operation not valid: Control 'Pie' accessed from a thread other than the thread it was created on.

Hoe kan ik dit oplossen? (en niet alleen voor dit, maar ook voor al het andere wat ik nog ga maken?)

Ik heb om een textBox te updaten de InvokeRequired gebruikt (zoals in jouw voorbeeld).

Bovenstaande fout gaat
Code:
Graphics g = System.Drawing.Graphics.FromHwnd(Pie.Handle);


Bedankt
 
Laatst bewerkt:
Het beste kun je dan (tenminste in pre framework 4, mogelijk is er nu een betere methode) een "delegate" aanmaken.

Vervolgens kun je met een:

Code:
xxx.invoke (new delegatesub("echte"sub))

de sub asynchroon aanroepen. Delegates worden door de form in een rij gezet en uitgevoerd in onbepaalde volgorde.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan