Thomas Nielsen - getCore
Приложение C# для Windows? Предположим, вы имеете в виду устаревшее приложение Windows Forms, тогда я взял на себя труд привести пример, объясняющий эту концепцию. В основном вам нужно увести свои вычисления подальше от потока пользовательского интерфейса, но не забудьте получить обновления для ваших элементов управления пользовательского интерфейса, выполняемых на нем.
Я взял на себя смелость использовать списки вместо текстовых полей, так как текстовые поля просто глупы для отображения текущих значений в IMO, не стесняйтесь менять это, хотя если есть какая-то веская причина :)
Итак, стандартная форма с двумя списками в самой левой части, кнопкой запуска и остановки и меткой, указывающей, запущены ли приложения. Я использую случайный объект для сна обновлений на другой случайный период между 100-2000 миллисекундами, чтобы имитировать вычисления.
использование таймера очень распространено для обеспечения повторяющихся событий, при использовании такого таймера он имеет свой собственный поток и должен быть осторожен, чтобы не выполнять несколько событий одновременно (например, при выполнении события с таймером происходит больше времени, чем время между событиями.)
Обновление: теперь добавлено и использование чисел, так как у запросчика было такое желание
С фоновым кодом:
using System;
using System.Threading;
using System.Windows.Forms;
namespace FormThings
{
public partial class TheForm : Form
{
private static Random Rnd { get; set; }
private delegate void ListboxUpdateDelegate(ListBox listbox);
public TheForm()
{
InitializeComponent();
Rnd = new Random((int)DateTime.Now.Ticks);
}
private volatile int _countOne = 0;
private volatile int _countTwo = 0;
private void TimeX_Tick(object sender, EventArgs e)
{
if (_timeExecuting)
return;
try
{
_timeExecuting = true;
int seedOne = Rnd.Next(100, 2000);
int seedTwo = Rnd.Next(100, 2000);
//var t1 = Task.Factory.StartNew((seed) => { UpdateControl(FirstListBox, (int)seed); },seedOne);
//var t2 = Task.Factory.StartNew((seed) => { UpdateControl(SecondListBox, (int)seed); }, seedTwo);
//Use below if you're compiling aganst older version of framework than 4.5
var state1 = new V35CompatibleContainer
{
ListBox = FirstListBox,
Seed = seedOne,
};
ThreadPool.QueueUserWorkItem(ExcecuteV35compatibleOnThreadPool, state1);
var state2 = new V35CompatibleContainer
{
ListBox = SecondListBox,
Seed = seedTwo,
};
ThreadPool.QueueUserWorkItem(ExcecuteV35compatibleOnThreadPool, state2);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception in time tick event: " + ex.ToString());
}
finally
{
_timeExecuting = false;
}
}
private volatile bool _timeExecuting = false;
private void ExcecuteV35compatibleOnThreadPool(object state)
{
var stateContainer = (V35CompatibleContainer)state;
UpdateControl(stateContainer.ListBox, stateContainer.Seed);
}
private class V35CompatibleContainer
{
public ListBox ListBox;
public int Seed;
}
private void UpdateControl(ListBox listBox, int seed)
{
System.Threading.Thread.Sleep(seed);
if (listBox.InvokeRequired)
{
listBox.BeginInvoke(new ListboxUpdateDelegate(InsertIncrementLoop), new object[] { listBox });
return;
}
InsertIncrementLoop(listBox);
}
private void InsertMoment(ListBox listBox)
{
listBox.Items.Insert(0, DateTime.Now.ToString("HH:mm:ss.fff"));
}
private void InsertIncrementLoop(ListBox listBox)
{
int theValueNumber = -1;
if (listBox.Name == "FirstListBox")
{
theValueNumber = Interlocked.Increment(ref _countOne);
if (theValueNumber == 10)
Interlocked.Exchange(ref _countOne, 0);
}
else
{
theValueNumber = Interlocked.Increment(ref _countTwo);
if (theValueNumber == 10)
Interlocked.Exchange(ref _countTwo, 0);
}
listBox.Items.Insert(0, theValueNumber.ToString());
}
private void ToggleRunmode()
{
StopButton.Enabled = !StopButton.Enabled;
StartButton.Enabled = !StopButton.Enabled;
if (StopButton.Enabled)
{
FirstListBox.Items.Clear();
SecondListBox.Items.Clear();
}
TimeX.Enabled = StopButton.Enabled;
RunningLabel.Visible = StopButton.Enabled;
}
private void StartButton_Click(object sender, EventArgs e)
{
ToggleRunmode();
}
private void StopButton_Click(object sender, EventArgs e)
{
ToggleRunmode();
}
private void TheForm_Load(object sender, EventArgs e)
{
}
}
}
Дизайнер:
namespace FormThings
{
partial class TheForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.StartButton = new System.Windows.Forms.Button();
this.StopButton = new System.Windows.Forms.Button();
this.FirstListBox = new System.Windows.Forms.ListBox();
this.SecondListBox = new System.Windows.Forms.ListBox();
this.RunningLabel = new System.Windows.Forms.Label();
this.TimeX = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// StartButton
//
this.StartButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.StartButton.Location = new System.Drawing.Point(337, 13);
this.StartButton.Name = "StartButton";
this.StartButton.Size = new System.Drawing.Size(75, 38);
this.StartButton.TabIndex = 0;
this.StartButton.Text = "&Start";
this.StartButton.UseVisualStyleBackColor = true;
this.StartButton.Click += new System.EventHandler(this.StartButton_Click);
//
// StopButton
//
this.StopButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.StopButton.Enabled = false;
this.StopButton.Location = new System.Drawing.Point(337, 57);
this.StopButton.Name = "StopButton";
this.StopButton.Size = new System.Drawing.Size(75, 38);
this.StopButton.TabIndex = 1;
this.StopButton.Text = "S&top";
this.StopButton.UseVisualStyleBackColor = true;
this.StopButton.Click += new System.EventHandler(this.StopButton_Click);
//
// FirstListBox
//
this.FirstListBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.FirstListBox.FormattingEnabled = true;
this.FirstListBox.Location = new System.Drawing.Point(13, 13);
this.FirstListBox.Name = "FirstListBox";
this.FirstListBox.Size = new System.Drawing.Size(122, 173);
this.FirstListBox.TabIndex = 2;
//
// SecondListBox
//
this.SecondListBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.SecondListBox.FormattingEnabled = true;
this.SecondListBox.Location = new System.Drawing.Point(141, 12);
this.SecondListBox.Name = "SecondListBox";
this.SecondListBox.Size = new System.Drawing.Size(122, 173);
this.SecondListBox.TabIndex = 3;
//
// RunningLabel
//
this.RunningLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.RunningLabel.AutoSize = true;
this.RunningLabel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int
virus131
Привет, Томас Нильсен, большое вам спасибо за ваше решение. Его абсолютно нормально работает и с текстовым полем. Но что делать, если я использую приведенный ниже код (в InsertMoment ()) вместо отображения даты и времени в моем текстовом поле-
частный недействительными InsertMoment(текстовое поле текстовое поле)
{
//текстовый.Текст = Датавремя.Сейчас.Метод toString("чч:мм:СС.ФФФ");
for (int i = 0; i < 10; i++)
{
текстовый.Text = i. ToString();
}
}
это не показывает правильный вывод значений 0-9 в текстовом поле.
Снова я изменил свой код, чтобы увидеть обновление 0-9 в текстовом поле как -
частный недействительными InsertMoment(текстовое поле текстовое поле)
{
//текстовый.Текст = Датавремя.Сейчас.Метод toString("чч:мм:СС.ФФФ");
for (int i = 0; i < 10; i++)
{
текстовый.Text = i. ToString();
Нить.Сон(100);
текстовое поле. обновить();
}
}
Это показывает обновление значений в текстовом поле, но одно за другим, означает, что это не обновляет оба текстовых поля одновременно. Я не знаю, возможно это или нет.
И если это возможно, то что делать, чтобы достичь этого.
Thomas Nielsen - getCore
То, что вы делаете, - это когда выполнение, так сказать, получает фокус, вы затем делаете быстрый цикл обновления каждого из значений, которого он достигает, скажем, от 0 до 10 всего за несколько миллисекунд. Следовательно, человеческий глаз не увидит.
Ваша вторая попытка затем состоит в том, чтобы обновить текстовое поле, ну, текстовое поле не является, скажем, привязанным к базе данных, так что обновление не приведет к желаемому изменению, и спать 100 миллисекунд = & gt; 1/10 секунды, ну, это очень вероятно, немного испортит пример, который имеет время, тикающее каждые 250 мс, и каждый раз, когда он это делает, он будет нести сон чего-то случайного между 0 и 2000 МС, ну, он мог бы выглядеть последовательным, не будучи на самом деле.
См. обновленное решение и, пожалуйста, отметьте вопрос как ответ, если вы считаете его таковым. :)