1

コンソールアプリケーションを作成しました。コンソールに入力した内容を(フォームに)ラベルに表示させたいのですが、フォームを実行するとコンソールがハングします。

コード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    class Program
    {
        Label a;
        static void Main(string[] args)
        {
            Form abc = new Form(); 
            Label a = new Label();
            a.Text = "nothing";
            abc.Controls.Add(a);
            Application.Run(abc);
            System.Threading.Thread t=new System.Threading.Thread(Program.lol);
            t.Start();


        }
        public static void lol()
        {
            Program p = new Program();
            string s = Console.ReadLine();
            p.a.Text = s;
            lol();
        }


    }
}
4

3 に答える 3

3

Application.Runフォームが閉じるまでブロックされます。したがって、別のスレッドで呼び出す必要があります。

ただし、UIはその別のスレッドで実行されます。UIスレッド以外のスレッドからUI要素に「タッチ」してはならないため、を呼び出した後、UIを使用または変更するConsole.ReadLine()必要があります。。Control.InvokeControl.BeginInvoke

さらに、現在、と呼ばれるローカル変数を宣言していますがa、に値を割り当てることはありませんProgram.a

動作する完全なバージョンは次のとおりです。

using System;
using System.Threading;
using System.Windows.Forms;

class Program
{
    private Program()
    {
        // Actual form is created in Start...
    }

    private void StartAndLoop()
    {
        Label label = new Label { Text = "Nothing" };
        Form form = new Form { Controls = { label } };
        new Thread(() => Application.Run(form)).Start();
        // TODO: We have a race condition here, as if we
        // read a line before the form has been fully realized,
        // we could have problems...

        while (true)
        {
            string line = Console.ReadLine();
            Action updateText = () => label.Text = line;
            label.Invoke(updateText);
        }
   }

    static void Main(string[] args)
    {
        new Program().StartAndLoop();
    }
}
于 2013-01-07T07:09:50.660 に答える
3

コードには多くの問題があります。名前の選択は含めません。

  • Application.Runブロッキングしています。Formコードの残りの部分は、が閉じられるまで呼び出されません。

  • あなたは再帰的に電話をかけていますlol()、そして私はそれを提案しません。while代わりにループを使用してください。

  • Labelコントロールが作成されたスレッドとは異なるスレッドからのテキストを設定しようとしています。Invokeまたは同様の方法を使用する必要があります。

これがあなたのコードがどうなるかの完全な例です。私はできるだけ少ないものを修正しようとしました。

class Program
{
    static Label a;

    static void Main(string[] args)
    {
        var t = new Thread(ExecuteForm);
        t.Start();
        lol();
    }

    static void lol()
    {
        var s = Console.ReadLine();
        a.Invoke(new Action(() => a.Text = s));
        lol();
    }

    public static void ExecuteForm()
    {
        var abc = new Form();
        a = new Label();
        a.Text = "nothing";
        abc.Controls.Add(a);
        Application.Run(abc);
    }
}
于 2013-01-07T07:10:47.240 に答える
2

新しいを作成する前に、フォームを生成しますThreadThreadこれは、が終了するまで、プログラムが実際に新しいものを作成することはないことを意味しますForm

あなたが使用する必要があります

System.Threading.Thread t = new System.Threading.Thread(Program.lol);
t.Start();
Application.Run(abc);
于 2013-01-07T07:05:15.107 に答える