Lilith.Cal Ответов: 3

C# как заставить текст отображаться в текстовом поле во время цикла?


У меня есть цикл, в котором я храню некоторые файлы в сжатом файле, и иногда это занимает некоторое время. Я попытался поместить уведомление о том, какой файл обрабатывается, в текстовое поле, чтобы пользователь знал, что происходит прогресс. Но текст отказывается представляться.

Цикл находится в основном потоке, поэтому мне не нужна функция обратного вызова.

Я не занимался программированием уже три года, но не помню, чтобы у меня тогда была такая проблема.

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

В любом случае создал функцию обратного вызова, но вызов никогда не требуется.

3 Ответов

Рейтинг:
27

Dave Kreskowiak

Правильный способ сделать это-переместить цикл в фоновую задачу или использовать BackgroundWorker[^].

То, что вы делаете, - это поддерживаете "длительную" работу в потоке пользовательского интерфейса, не позволяя элементам управления пользовательского интерфейса отвечать на сообщения, которые говорят им перекрашивать себя новыми данными.


Рейтинг:
15

RickZeeland

Вы можете использовать Приложение.Функция doevents() в Windows Forms см. пример здесь: Приложение.Метод DoEvents (System.Окна.Формы) | Microsoft Docs[^]


Рейтинг:
11

George Swan

Проблема в том, что ваш длительный метод блокирует поток пользовательского интерфейса. Я бы предположил, что решение состоит в том, чтобы использовать Асинхронный шаблон на основе задачВам нужно запустить свой длительный метод в его собственном потоке и заставить его сообщать о своем прогрессе потоку пользовательского интерфейса в виде string Затем вы можете вставить возвращенную строку в TextBlock Вот демонстрационный консольный проект, который покажет вам основную идею.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace DemoAsync
{
    // To get async Main to run you may need to change the language version
    //In Solution Explorer/Properties/Build/Advanced 
    //Select 'C# latest supported minor version (latest)' in the Language Version list
    class Program
    {
        private static async Task Main()
        {
            var progress = new Progress<string>();
            //Define the handler. It will be run on the UI  thread
            //In this example the handler is writing the text to the console
            //But you can put it in a TextBox
            progress.ProgressChanged +=
                 ((sender, text) => Console.WriteLine(text));
            await Task.Run(() => MyLongRunningMethod(progress));
            Console.WriteLine("Hit 'return' to finish");
            Console.ReadLine();

        }

        private static void MyLongRunningMethod(IProgress<string> progress)
        {
            int max = 10;
            //simulation of a long-running method
            //It reports progress every second
            for (int i = 1; i <= max; i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));

                progress.Report(i.ToString());
            }


        }
    }
}