У меня есть приложение с кнопкой запуска, которая вызывает функцию продолжительного времени работы. В порядке , чтобы добавить кнопку Stop. Я добавил поток для этой функции, чтобы избежать зависания пользовательского интерфейса и иметь возможность остановить обработку в любое время.Усиление производительности для потоковой передачи
Код без нарезки в среднем занимает 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");
}
}
Update: Единственное, что я изменил путь я объявляю функции и добавил, если заявление внутри цикла в то время как , который находится внутри функции. Как показано ниже:
- Отмена CancelToken была добавлена для того, чтобы остановить обработку при нажатии кнопки Stop.
без резьбы Объявляю функцию следующим образом:
public void LongRunningFunction(string String)
{
while (condition)
{
//My code within While loop
}
MessageBox.Show("Processing finished");
}
и Thread я определить функцию так:
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
}
};
}
Выполнение кода в дополнительной ветке вместо потока пользовательского интерфейса не должно уменьшать производительность в четыре раза (и не должно увеличивать производительность, так как выполняется точно такая же работа, обрабатывать или обрабатывать несколько оконных сообщений). Что еще вы изменили? Что вы делаете с «CancellationToken», чего не было в исходном коде? – CodeCaster
Вы должны использовать 'TaskCreationOptions.LongRunning', если операция занимает 12 минут, а не то, что приведет к замедление 4x, которое вы видите. – Servy
Ваш LongRunningFunction() обновляет пользовательский интерфейс, если это возможно (с помощью диспетчера или любого другого механизма) ?. Если нет, я не вижу, как это повлияет на производительность вообще. – kha