virus131 Ответов: 2

Отображение значений в текстовом поле


Привет,
Я хочу непрерывно отображать некоторые вычисленные значения в двух текстовых полях в моем приложении C# windows. Это выполнение должно выполняться одновременно, что означает, что оба текстовых поля должны обновляться одновременно, но не одно за другим. Я использую Visual Studio 2008.

Пожалуйста, помогите мне.... Я совершенно новичок в этом деле.

Спасибо.

Что я уже пробовал:

Я пытаюсь сделать это с помощью резьбы, но так же, как я использую резьбу.Sleep (1000), обновление во втором текстовом поле начинается через 1 секунду. Для чтения значений в текстовом поле необходимо использовать Sleep (). Пожалуйста, предложите альтернативный метод Sleep (), чтобы пользователь мог читать значения в текстовом поле ,а также второй поток не будет заблокирован.

Ralf Meier

Я думаю, что решение CPallini не соответствует вашему вопросу - но я не уверен.
Пожалуйста, объясните еще раз, с помощью некоторого кода, который показывает, что вы кодировали до сих пор, чего вы пытаетесь достичь.
Элементы управления (например, текстовые поля) принадлежат основному потоку и не могут быть напрямую доступны через подпоток. Для этого вы должны использовать He Invoke-метод элементов управления, который говорит им, что есть что-то делать, когда основной поток вернет элемент управления.
Если вы пишете Sleep (0) внутри своего потока, вы позволяете главному потоку на короткое время выполнить необходимые действия.

virus131

На самом деле я попробовал это сделать, используя метод Invoke, а также метод BeginInvoke. но он не работает должным образом.

Ralf Meier

.. затем покажите свой код (улучшите свой вопрос с помощью фрагмента кода)

2 Ответов

Рейтинг:
7

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

привет... спасибо за ответ.. но я использую C# 3.5

Thomas Nielsen - getCore

Только что обновленное решение для версии 3.5.

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 МС, ну, он мог бы выглядеть последовательным, не будучи на самом деле.

См. обновленное решение и, пожалуйста, отметьте вопрос как ответ, если вы считаете его таковым. :)

Рейтинг:
0

CPallini

Цитата:
Это выполнение должно выполняться одновременно, что означает, что оба текстовых поля должны обновляться одновременно

Это невозможно, ты же знаешь.
Однако если вы пишете, например
textbox1.Text = "foo";
textbox2.Text = "boo";
// .. some delay here

Пользователь будет воспринимать это как одновременное обновление.