我有一個應用程序,帶有一個調用長時間運行時間函數的啓動按鈕。爲了增加一個停止按鈕,我爲此添加了一個線程,以避免UI凍結,並能夠隨時停止處理。提高線程性能
沒有線程的代碼平均需要12分鐘才能完成處理,但通過線程的方式,我在 以下的方式需要4倍多。下面顯示的是啓動按鈕的代碼,其中稱爲函數「LongRunningFunction」。函數 需要一個字符串參數才能工作「LongRunningFunction(Somestring)」。
我已經用Task.Run和Task.Factory.StartNew進行了測試,但是兩種方法都發生了相同的情況。
是否有另一種方法來設置一個線程爲我的情況,不會影響太多的性能?
public partial class Form1 : Form
{
CancellationTokenSource cts = new CancellationTokenSource(); // Create the token source.
public Form1()
{
InitializeComponent();
}
private void Start_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
}
cts = new CancellationTokenSource();
Task.Run(()=> LongRunningFunction(Somestring, cts.Token), cts.Token);
//Task.Factory.StartNew(() => LongRunningFunction(Somestring, cts.Token), cts.Token, TaskCreationOptions.None, TaskScheduler.Default);
}
private void Stop_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
cts = null;
MessageBox.Show("Processing cancelled");
}
}
public void LongRunningFunction(string String, CancellationToken token)
{
//Long running processing
//...
MessageBox.Show("Processing finished");
}
}
更新: 唯一的東西我改變的是我聲明功能,並增加了的方式,如果while循環 是在函數內部內聲明。如下所示:
- 已添加CancelationToken以便能夠在按下停止按鈕時停止處理。
無螺紋我聲明函數是這樣的:
public void LongRunningFunction(string String)
{
while (condition)
{
//My code within While loop
}
MessageBox.Show("Processing finished");
}
與線程我這樣定義函數:
public void LongRunningFunction(string String, CancellationToken token)
{
while (condition)
{
if (token.IsCancellationRequested)
{
break;
}
//My code within While loop
}
if (!token.IsCancellationRequested)
{
MessageBox.Show("Processing finished");
}
}
UPDATE2: 內LongRunningFunction()被調用另一個打印行的功能。就像下面。
public void LongRunningFunction(string fileName, CancellationToken token)
{
StreamWriter writer = new StreamWriter(@outputfile, true, Encoding.UTF8, 4096);
using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
{
List<byte> buffer = new List<byte>();
List<string> buffer1 = new List<string>();
SoapHexBinary hex = new SoapHexBinary();
while (chunk.Length > 0)
{
if (token.IsCancellationRequested) // ### For Cancel Thread ###
{
break;
} // ### For Cancel Thread ###
chunk = reader.ReadBytes(1024);
foreach (byte data in chunk)
{
if (somecondition)
{
buffer.Add(data);
}
else if (other condition)
{
buffer.Add(data);
PrintFunction(buffer, hex, outputfile, writer); // Print Line
}
else if (some other condition)
{
buffer.Add(data);
}
}
}
if (!token.IsCancellationRequested)
{
MessageBox.Show("Processing finished");
}
}
if (writer != null)
{
writer.Dispose();
writer.Close();
}
}
private void PrintFunction(List<byte> buffer, SoapHexBinary hex, string outputfile, StreamWriter writer)
{
if (buffer.Count > 0)
{
if (buffer.Count >= lowlimit)
{
hex.Value = buffer.ToArray();
string Register = hex.ToString();
Regex pattern1 = new Regex(@"some pattern");
if (pattern1.IsMatch(Register))
{
Match l1 = Regex.Match(Register, @"somepattern", RegexOptions.IgnoreCase | RegexOptions.Compiled);
writer.Write("{0}|{1}|{2}", Convert.ToInt32(l1.Groups[1].ToString(), 16), l1.Groups[2].Value, l1.Groups[3].Value);
Match l2 = Regex.Match(Register, @"otherpattern", RegexOptions.IgnoreCase | RegexOptions.Compiled);
if (l2.Success)
{
foreach (Match m in Regex.Matches(l2.Groups[2].ToString(), pattern2, RegexOptions.IgnoreCase | RegexOptions.Compiled))
{
//Some foreach code
}
foreach (Match x in Regex.Matches(var, @"pattern"))
{
//come code
}
writer.WriteLine("," + String.Join(",", var1));
}
else
{
writer.WriteLine();
}
}
}
}
buffer.Clear();
}
UPDATE3: 嗨bebosh,
我還是有疑問如何在我的功能應用,你的方式在您的示例功能定義委託。
我的功能看起來是這樣的:
public void LongRunningFunction(string fileName)
{
using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
{
// some code
}
}
這可能是這樣或如何?:
private void LongRunningFunction(string fileName)
{
MethodInvoker action = delegate
{
using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
{
// some code
}
};
}
在一個額外的線程而不是UI線程上運行代碼不應該降低性能4倍(它也不應該真的提高性能,因爲完成相同的工作,給予或處理幾個窗口消息)。你還有什麼改變?你如何處理原始代碼沒有的'CancellationToken'? – CodeCaster
如果操作需要12分鐘,您應該使用'TaskCreationOptions.LongRunning',而不是那會導致您看到的4倍放緩。 – Servy
您的LongRunningFunction()是否有任何機會(通過使用分派器或任何其他機制)更新UI?如果沒有,我看不出它會如何影響性能。 – kha