C# 为什么我的程序在计时器代码运行时会冻结?

C# 为什么我的程序在计时器代码运行时会冻结?,c#,C#,我的程序是在ROBLOX打开时自动打开另一个程序。我知道这很奇怪,但对我很有帮助。一旦程序打开,我的按钮和一切都可以正常工作。一旦我启用它并打开ROBLOX,应用程序就会中断,直到ROBLOX关闭。只是冻结,没有错误。也不会打开其他应用程序。请帮忙 using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Draw

我的程序是在ROBLOX打开时自动打开另一个程序。我知道这很奇怪,但对我很有帮助。一旦程序打开,我的按钮和一切都可以正常工作。一旦我启用它并打开ROBLOX,应用程序就会中断,直到ROBLOX关闭。只是冻结,没有错误。也不会打开其他应用程序。请帮忙

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ProtoSmasher_Auto_Opener
{
    public partial class Form1 : Form
    {
        string path;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if(!File.Exists(@"c:\PSAutoStart\path.proto"))
            {
                MessageBox.Show("It seems like this is your first time running. Please make sure File Manager is closed for your first run.", "Notice");
            }
            if (File.Exists(@"c:\PSAutoStart\path.proto"))
            {
                string lastPath;
                using (StreamReader sr = new StreamReader(@"c:\PSAutoStart\path.proto"))
                {
                    lastPath = sr.ReadToEnd();
                }
                textBox1.Text = lastPath;
                path = lastPath;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (button1.BackColor != System.Drawing.Color.Red)
            {
                if(textBox1.Text == "")
                {
                    MessageBox.Show("Please click browse and locate ProtoSmasher to activate.", "Error");
                }
                else
                {
                    button1.BackColor = System.Drawing.Color.Red;
                    button1.Text = "Deactivate";
                    timer1.Start();
                }
            }
            else
            {      
                button1.BackColor = System.Drawing.Color.Green;
                button1.Text = "Activate";
                timer1.Stop();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Filter = "ProtoSmasher (*.exe)|*.exe";
            if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                path = fileDialog.FileName;
                if (!File.Exists(@"c:\PSAutoStart\path.proto"))
                {
                    DirectoryInfo di = Directory.CreateDirectory(@"c:\PSAutoStart");
                    try
                    {
                        System.Threading.Thread.Sleep(2 * 1000);
                        StreamWriter sw = File.CreateText(@"c:\PSAutoStart\path.proto");
                        sw.WriteLine(path);
                        textBox1.Text = path;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Didn't I tell you to close your file manager first?", "Error");
                    }
                }
                else
                {
                    using (StreamWriter sw = File.CreateText(@"c:\PSAutoStart\path.proto"))
                    {
                        sw.WriteLine(path);
                    }
                    textBox1.Text = path;
                }
            }

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Process[] roblox = Process.GetProcessesByName("RobloxPlayerBeta");
            if (roblox.Length > 0)
            {
                try
                {
                    Process.Start(textBox1.Text);
                    stillRunning.Start(); //to keep from spamming open
                    timer1.Stop(); 
                }
                catch(Exception ex)
                {
                    MessageBox.Show("Something went wrong: " + ex, "Error");
                }
            }
        }

        private void stillRunning_Tick(object sender, EventArgs e)
        {
            Process[] roblox = Process.GetProcessesByName("RobloxPlayerBeta");
            if(roblox.Length > 0)
            { }
            else
            {
                timer1.Start();
                stillRunning.Stop();
            }
        }
    }
}

在.NET中有十几个计时器。我想知道这是Windows窗体计时器:

每个线程只能运行一段代码。WindowsForms计时器在GUI线程中运行。计时器在这方面有很多变化,但是您可能还必须处理交叉线程安全问题。我想你应该在组合中加入一些明确的多任务处理

多任务处理是一个非常棘手的问题,需要学习。我通常的学习建议是在WindowsForms应用程序中使用BackgroundWorker。您可能不想在生产代码中看到它,但它是一个非常好的“训练轮”。我还有一些关于如何使用它的老例子:

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
    if (!bgwPrim.IsBusy)
    {
        //Prepare ProgressBar and Textbox
        int temp = (int)nudPrim.Value;
        pgbPrim.Maximum = temp;
        tbPrim.Text = "";

        //Start processing
        bgwPrim.RunWorkerAsync(temp);
    }
}

private void btnPrimCancel_Click(object sender, EventArgs e)
{
    if (bgwPrim.IsBusy)
    {
        bgwPrim.CancelAsync();
    }
}

private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
    int highestToCheck = (int)e.Argument;
    //Get a reference to the BackgroundWorker running this code
    //for Progress Updates and Cancelation checking
    BackgroundWorker thisWorker = (BackgroundWorker)sender;

    //Create the list that stores the results and is returned by DoWork
    List<int> Primes = new List<int>();


    //Check all uneven numbers between 1 and whatever the user choose as upper limit
    for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
    {
        //Report progress
        thisWorker.ReportProgress(PrimeCandidate);
        bool isNoPrime = false;

        //Check if the Cancelation was requested during the last loop
        if (thisWorker.CancellationPending)
        {
            //Tell the Backgroundworker you are canceling and exit the for-loop
            e.Cancel = true;
            break;
        }

        //Determin if this is a Prime Number
        for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
        {
            if (PrimeCandidate % j == 0)
                isNoPrime = true;
        }

        if (!isNoPrime)
            Primes.Add(PrimeCandidate);
    }

    //Tell the progress bar you are finished
    thisWorker.ReportProgress(highestToCheck);

    //Save Return Value
    e.Result = Primes.ToArray();
}

private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    pgbPrim.Value = e.ProgressPercentage;
}

private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    pgbPrim.Value = pgbPrim.Maximum;
    this.Refresh();

    if (!e.Cancelled && e.Error == null)
    {
        //Show the Result
        int[] Primes = (int[])e.Result;

        StringBuilder sbOutput = new StringBuilder();

        foreach (int Prim in Primes)
        {
            sbOutput.Append(Prim.ToString() + Environment.NewLine);
        }

        tbPrim.Text = sbOutput.ToString();
    }
    else 
    {
        tbPrim.Text = "Operation canceled by user or Exception";
    }
}
#endregion
#区域素数
私有无效btnPrimStart\单击(对象发送者,事件参数e)
{
如果(!bgwPrim.IsBusy)
{
//准备进度条和文本框
int temp=(int)nudPrim.Value;
pgbPrim.最大值=温度;
tbPrim.Text=“”;
//开始处理
bgwPrim.RunWorkerAsync(临时);
}
}
私有无效btnprimmcancel\u单击(对象发送者,事件参数e)
{
如果(bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
私有void bgwPrim_DoWork(对象发送方,DoWorkEventArgs e)
{
int highestToCheck=(int)e.参数;
//获取运行此代码的BackgroundWorker的引用
//用于进度更新和取消检查
BackgroundWorker thisWorker=(BackgroundWorker)发件人;
//创建存储结果并由DoWork返回的列表
列表素数=新列表();
//检查1和用户选择的任何上限之间的所有不均匀数
对于(int PrimeCandidate=1;PrimeCandidate

然而,我有点不确定你的程序甚至做什么。使用特定字符串获取所有进程并强制关闭它们?

在.NET中,只有十几个计时器。那是哪一个?这是WindowsForms计时器:它在主线程中运行。你需要在这里使用某种形式的多任务处理。对于初学者,我建议在WindowsForm中使用BackgroundWorker。我熟悉c#,但并不擅长。是否有关于后台工作人员及其工作方式的文档?这可能也值得一读:不,这不是强制关闭任何文件。基本上,当ROBLOX打开时,程序应该会检测到它。一旦检测到,它将打开另一个应用程序并停止计时器,这样它就不会打开该应用程序。第二个计时器确保ROBLOX仍在运行,当它没有运行时,再次启动计时器以检测ROBLOX。@Zeridiant听起来像是一个不需要UI的执事,因此可以通过轮询锁定其主线程。当然,如果请求取消,它需要一种中断轮询的方法。甚至可能是Windows服务在任何程序中添加执事功能都是可能的,但是你总是需要一个额外的线程来完成这项工作。@Zeridiant然而,通常对某些事情做出反应的最佳方式是首先启动它。如果您需要桌面链接,DRM/更新程序系统(如Steam或Epic)将使用一个技巧作为启动程序,并且仍然有一个桌面图标:Web链接。您可以设置要注册到某些协议的程序,包括自定义的“steam:”和“com.epicgames.launcher:”。添加一些单实例机制,将请求中继到正在运行的实例中,这样就可以了。