気象学の授業で書きました。何らかの理由で、GUI のテキストボックスが多数 (フォトンの数が多い) の場合、正しく更新されません。計算は完了しますが、テキスト ボックスは更新されません。
問題は Invoke() の呼び出しにあると思われますが、何がうまくいかないのか一生わかりません。Invoke() と BeginInvoke() の両方を使用してみましたが、同様の結果が得られました。
誰かが私が間違っている場所を理解するのを助けることができますか?
ありがとう!
PS>グローバル変数を許してください。後で掃除するつもりだったのに…
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace CloudTransmittance
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonCalculate_Click(object sender, EventArgs e)
{
Thread t = new Thread(calculateModel);
t.Start();
}
//number of photons that have gone to albedo, direct, or diffuse transmittance
private ulong top = 0;
private ulong direct = 0;
private ulong diffuse = 0;
private ulong absorbed = 0;
private ulong failed = 0;
private ulong photons = 0;
private void calculateModel()
{
//model variables
double theta = 0;
double tauStar = 0;
double omega = 0;
double g = 0;
photons = 0;
//Get data from form
theta = Convert.ToDouble(textBoxTheta.Text);
tauStar = Convert.ToDouble(textBoxTau.Text);
omega = Convert.ToDouble(textBoxOmega.Text);
g = Convert.ToDouble(textBoxG.Text);
photons = Convert.ToUInt64(textBoxPhotons.Text);
//Clear the progress bar and set its limits
this.progressBar1.BeginInvoke(
(MethodInvoker)delegate()
{
this.progressBar1.Minimum = 0;
this.progressBar1.Value = 0;
this.progressBar1.Maximum = (int)photons;
this.progressBar1.Step = 1;
});
//Clear the text boxes
this.textBoxAlbedo.Invoke(
(MethodInvoker)delegate()
{
this.textBoxAlbedo.Text = "";
});
this.textBoxDirect.Invoke(
(MethodInvoker)delegate()
{
this.textBoxDirect.Text = "";
});
this.textBoxDiffuse.Invoke(
(MethodInvoker)delegate()
{
this.textBoxDiffuse.Text = "";
});
this.textBox1.Invoke(
(MethodInvoker)delegate()
{
this.textBox1.Text = "";
});
this.textBox2.Invoke(
(MethodInvoker)delegate()
{
this.textBox2.Text = "";
});
//convert theta to radians from degrees
theta *= Math.PI / 180;
//number of photons that have gone to albedo, direct, or diffuse transmittance
top = 0;
direct = 0;
diffuse = 0;
absorbed = 0;
failed = 0;
//Random number generator
Random r = new Random();
double randomValue = 0;
int count = 1000; //number of iterations of the problem...
double delta = 0.00001; //close enough to "1" for calculations, since C# random goes from [0, 1) instead of [0, 1]
//Calculate transmittance
for (ulong photonCount = 0; photonCount < photons; photonCount++)
{
bool scattered = false;
double newTheta = theta; //needed for looping
int i = 0; //counting variable used to prevent infinite looping
for (i = 0; i < count; i++)
{
double length = calculateTauP(); //length of the photon's travel
double newTau = calculateTau(newTheta, length);
if (newTau < 0)
{
top++; //photon has exited through the top
break; //move to the next photon
}
else if (newTau > tauStar)
{
//exited through the bottom of the cloud
if (scattered == false)
{
//direct transmittance
direct++;
}
else
{
//diffuse transmittance
diffuse++;
}
break;
}
else
{
//photon is either scattered or absorbed
randomValue = r.NextDouble();
if (randomValue >= omega) // || ((omega == 1) && (randomValue >= (omega - delta)) )
{
//photon absorbed, no longer of interest
absorbed++;
break;
}
else
{
//photon scattered, determine direction
scattered = true;
newTheta = calculateNewAngle(newTau, newTheta, g, randomValue);
}
}
}
if (i >= count)
{
failed++;
}
this.progressBar1.BeginInvoke(
(MethodInvoker)delegate()
{
this.progressBar1.PerformStep();
});
}
//Update Form values
displayData();
}
private void displayData()
{
if (this.textBoxAlbedo.InvokeRequired)
{
this.textBoxAlbedo.Invoke(
(MethodInvoker)delegate()
{
this.textBoxAlbedo.Text = ((double)top / (double)photons).ToString();
});
}
else
{
textBoxAlbedo.Text = ((double)top / (double)photons).ToString();
}
if (this.textBoxDirect.InvokeRequired)
{
this.textBoxDirect.Invoke(
(MethodInvoker)delegate()
{
this.textBoxDirect.Text = ((double)direct / (double)photons).ToString();
});
}
else
{
textBoxDirect.Text = ((double)direct / (double)photons).ToString();
}
if (this.textBoxDiffuse.InvokeRequired)
{
this.textBoxDiffuse.Invoke(
(MethodInvoker)delegate()
{
this.textBoxDiffuse.Text = ((double)diffuse / (double)photons).ToString();
});
}
else
{
textBoxDiffuse.Text = ((double)diffuse / (double)photons).ToString();
}
if (this.textBox1.InvokeRequired)
{
this.textBox1.Invoke(
(MethodInvoker)delegate()
{
this.textBox1.Text = absorbed.ToString();
});
}
else
{
textBox1.Text = absorbed.ToString();
}
if (this.textBox2.InvokeRequired)
{
this.textBox2.Invoke(
(MethodInvoker)delegate()
{
this.textBox2.Text = failed.ToString();
});
}
else
{
textBox2.Text = failed.ToString();
}
}
private double calculateNewAngle(double length, double angle, double g, double randomNumber)
{
double newAngle = 0;
double cos = (1 / (2 * g)) * (1 + Math.Pow(g, 2) - Math.Pow(((1 - Math.Pow(g, 2)) / (1 + g * (2 * randomNumber - 1))), 2));
newAngle += angle + cos;
while (newAngle >= 2 * Math.PI)
{
newAngle -= 2 * Math.PI; //normalize the angle to 0 <= angle < 2PI
}
return newAngle;
}
private double calculateTauP()
{
Random r = new Random();
double distance = -1 * Math.Log(1 - r.NextDouble());
return distance;
}
private double calculateTau(double angle, double tauP)
{
double tau = tauP * Math.Cos(Math.PI/2 - angle);
return tau;
}
}
}