0

よし、これで契約だ。GUI アプリケーションであるが GUI を持たないアプリケーションを作成しようとしています。そのため、アプリケーションが起動すると、ログイン画面のある小さなフォームが表示されます (この部分は実行済みです)。

これはフォームが実行されるコードですがmain()、フォームが閉じられるとすぐに破棄します。

static void Main() 
{       
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);                        
    //Create an instance of form1
    Form1 form1 = new Form1();          
    Application.Run(form1);

    if(form1.isLoggedIn) 
    {             
        filename = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username);
        Flow palm = new Flow(new FlowArguments(form1.username, filename));
        MessageBox.Show("Thankyou, exiting...");
        form1.Dispose();                
    } 
}

フォームが閉じられた後もわかるように、メインは誰かがログインしている状態で続行されます。注意深く見ると、Flow作成されたクラスのインスタンスがあります。

これは非常に短いクラスです。

public class Flow 
{
    //global variables
    FlowArguments FlowArgs;
    System.Threading.Timer tm;

    //constructor
    public Flow(FlowArguments fmg) 
    {
        FlowArgs = fmg;

        tm = new System.Threading.Timer(Tick, null, 
                                            System.Threading.Timeout.Infinite, 10000);


        using(StreamWriter sw = new StreamWriter(FlowArgs.Filename)) 
        {            
            //sw.writelines that SO doesnt really care for.               
        }

        //enable the timer
        tm.Change(0, 100);
    }

    public void Tick(object State) 
    {
        Console.WriteLine("Hello");
        //a bunch of SteamWriter writeline methods that SO doesnt care for.
    }

    public void WriteProcesses(StreamWriter sw, DateTime dw) 
    {
        var localAll = Process.GetProcesses().Where(o => o.ProcessName.ToLower() != "svchost");
        foreach(Process p in localAll) 
        {
            sw.WriteLine("@" + p.ProcessName +
                         "[" + dw.ToString("ddMMyyhhmm") + "]" +
                         "[" + FlowArgs.Username + "]");
        }              
    }
}

ご覧のとおり、タイマーを開始します。しかし、これは(実際には適切ではないことSystem.Threading.Timerをどこかで読んだため)スレッドプールで実行されるため(MSDNに従って)、これが発生している間にメインフォームが終了したため、プログラムが閉じられます。Form.TimerMain()

私の可能な解決策は何ですか?このタイマーは 10 分ごとに実行されます (プロセスを取得します)。GUI を閉じた後、ユーザーがプログラムを閉じるために使用できるシステム アイコン トレイを作成する予定です。

4

3 に答える 3

3

そのスレッドのものをすべて削除し、システムトレイアイコンを実装するフォームですべてを実行します。タイマーをその形にすると、必要なことがすべて完了します。

何かのようなもの

LoginForm login = new LoginForm();
if(login.ShowDialog()==DialogResult.OK)
{
    Application.Run(new SystemTrayForm());
}
于 2009-01-12T03:15:08.133 に答える
0

ありがとう、それが私が必要としているものなので、これが私が実装したものです:

if(form1.isLoggedIn) {             
    //Create a wait handle for the UI thread.
    AutoResetEvent hold = new AutoResetEvent(false);

    filename = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username);
    Flow palm = new Flow(new FlowArguments(form1.username, filename), hold);

    //wait for the background thread to finish.
    hold.WaitOne(Timeout.Infinite);

    MessageBox.Show("Thankyou, exiting...");
    form1.Dispose();                
} 

ご覧のとおり、AutoResetEvent (MSDN タイマー クラスの例から) の参照が Flow クラスのコンストラクターに渡されます。そこから、「set」メソッドを呼び出して、待機中のスレッドを解放できます。私は今それを理解しています。

でも

hold.WaitOne(Timeout.Infinite);

不確定な時間を待ちます.フロークラスに「コマンド」を送信してタイマーを停止し、ウェイトハンドルで「設定」メソッドを呼び出して、UI スレッドを終了できるようにしたいと思います..

「シグナル」を送るにはどうすればいいですか?

注: システム トレイ アイコンをどこに配置するかはまだ決めていません。だから、それを Flow クラスに入れる方が簡単なら、そうします。

于 2009-01-12T02:49:14.877 に答える
0

フォアグラウンド スレッドを待機させたい場合は、WaitHandle を使用できます。

http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx

于 2009-01-12T02:30:19.613 に答える