C# 在读取输入时进行计算的窗口窗体应用程序

C# 在读取输入时进行计算的窗口窗体应用程序,c#,multithreading,visual-studio-2017,C#,Multithreading,Visual Studio 2017,我正在尝试编写一个Windows窗体应用程序,用于计算小于10^20的数字的素因式分解。但当数字大于10^12时,应用程序在给出结果前几秒钟开始冻结。所以我尝试创建一个线程来分别计算答案。代码如下: class fact { static long[] res = new long[202]; static long num; public static string output; static void cal

我正在尝试编写一个Windows窗体应用程序,用于计算小于10^20的数字的素因式分解。但当数字大于10^12时,应用程序在给出结果前几秒钟开始冻结。所以我尝试创建一个线程来分别计算答案。代码如下:

    class fact
    {
        static long[] res = new long[202];
        static long num;
        public static string output;

        static void calcFact(long n)
        {
            //calculate prime factorization into array res
        }    

        static void call()
        {
            calcFact(s);
        }

        public static void execute(string input)
        {
            s = long.Parse(input);
            ThreadStart childref = new ThreadStart(call);
            Thread childThread = new Thread(childref);
            childThread.Start();
            for (int i = 0; i < len; i++) output += res[i].ToString() + " ";
        }
    }

    private void InputBox_TextChanged(object sender, EventArgs e)
    {
        if (InputBox.Text != "")
        {
            fact.execute(InputBox.Text);
            output.Text = fact.output;
        }
    }            
类事实
{
静态long[]res=新long[202];
静态长数;
公共静态字符串输出;
静态空隙计算(长n)
{
//计算数组res的素因子分解
}    
静态void调用()
{
calcFact(s);
}
公共静态void执行(字符串输入)
{
s=long.Parse(输入);
ThreadStart childref=新的ThreadStart(调用);
线程childThread=新线程(childref);
childThread.Start();
对于(int i=0;i

在不创建新线程的情况下,应用程序可以工作,但现在输出总是空的。有人能解释一下这个线程是如何运行的以及如何修复它的吗?

这是因为您正在启动该线程,并在尝试显示其结果之后立即启动该线程。您必须等待线程完成,为此,您可以使用
BackgroundWorker

class fact {
/*...*/
static void calcFact(long n, BackgroundWorker worker)
    {
        if (worker.CancellationPending == true)
        {
            e.Cancel = true;
            break;
        } 
        //do this code in your loop to break and stop the calculation
        //calculate prime factorization into array res
    }   

var backgroundWorker = new System.ComponentModel.BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        backgroundWorker_RunWorkerCompleted);
backgroundWorker.WorkerSupportsCancellation = true;

private void backgroundWorker_DoWork(object sender, 
        DoWorkEventArgs e)
    {   
        BackgroundWorker worker = sender as BackgroundWorker;
        // Assign the result of the computation
        // to the Result property of the DoWorkEventArgs
        // object. This is will be available to the 
        // RunWorkerCompleted eventhandler.

        var result = calcFact((long)e.Argument, worker);
        var outputBkw = string.Empty;
        for (int i = 0; i < len; i++) outputBkw += res[i].ToString() + " ";
        e.Result = outputBkw;
    }

    private void backgroundWorker_RunWorkerCompleted(
        object sender, RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown.
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            // Next, handle the case where the user canceled 
            // the operation.                
            resultLabel.Text = "Canceled"; // or any other method you are showing status...
        }
        else
        {
            // Finally, handle the case where the operation 
            // succeeded.
            resultLabel.Text = e.Result.ToString();
            //Here you can use the result with the numbers calculated.
            // At this point you can have an event in the calc class to signal that the work is finished.
        }            
    }


private void cancelAsyncButton_Click(object sender, EventArgs e)
    {
        if (backgroundWorker.WorkerSupportsCancellation == true)
        {
            // Cancel the asynchronous operation.
            backgroundWorker.CancelAsync();
        }
    }
类事实{
/*...*/
静态无效计算(长n,后台工作人员)
{
if(worker.CancellationPending==true)
{
e、 取消=真;
打破
} 
//在循环中执行此代码可以中断并停止计算
//计算数组res的素因子分解
}   
var backgroundWorker=new System.ComponentModel.backgroundWorker();
backgroundWorker.DoWork+=新的DoworkerVenthandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(
后台工作人员(运行工作已完成);
backgroundWorker.WorkerSupportsScanCellation=true;
私有void backgroundWorker_DoWork(对象发送方,
道夫特(e)
{   
BackgroundWorker worker=发件人作为BackgroundWorker;
//分配计算结果
//到DoWorkEventArgs的结果属性
//对象。这将可用于
//RunWorkerCompleted eventhandler。
var result=calcFact((长)e.参数,worker);
var outputBkw=string.Empty;
对于(int i=0;i
更新


要启用取消,您必须在声明后台工作人员时使用
backgroundWorker.WorkerSupportsCancellation=true;
。我已经更新了代码示例以考虑这一点。

阅读
backgroundWorker
,尤其是
RunWorkerCompleted
。您只需处理后台工作人员当数值太大时,计算变得不实际。尝试停止并重新启动线程会给您带来很多麻烦,这是充满竞争条件的。保持简单,当值足够小时立即计算结果,进行“计算”按钮不可见时可见。用户如何取消操作?