Подтвердить что ты не робот

"Не реагировать" в заголовке окна при запуске в новом процессе

У меня есть длинный метод, который должен запускаться в потоке пользовательского интерфейса. (Devex - gridView.CopyToClipboard())

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

Когда я запускаю эту программу, все хорошо.

Неисправность начинается, когда я запускаю другую программу, которая, в свою очередь, запускает новый процесс и запускает на нем программу. Через несколько секунд после копирования заголовок читает (Not Responding), и курсор мыши показывает занятый, он, конечно, очищается в течение нескольких секунд, но я хотел бы избавиться от него, так как он дает пользователю неправильное ощущение, что программа неисправен.

Есть ли способ установить "Тайм-аут" процесса, который я создаю?

EDIT:

Основная программа вызывает следующий код:

fillsProcess = new Process();
fillsProcess.StartInfo.FileName = Application.ExecutablePath;
fillsProcess.Start();

В fillsProcess, когда нажимается определенная кнопка, вызывается следующий код:

gridViewToCopy.CopyToClipboard();

Эта строка кода занимает некоторое время, и через несколько секунд окно fillsProcess выглядит невосприимчивым, поскольку этот метод работает в потоке пользовательского интерфейса.

РЕДАКТИРОВАТЬ 2-й:

По-видимому (и действительно вполне понятно)

gridViewToCopy.CopyToClipboard();

Не единственный метод, вызывающий эту проблему. Многие методы Devex должны запускаться в потоке пользовательского интерфейса (например, сортировка данных, фильтрация данных).

Так спасибо всем, кто предложил конкретное решение (которое либо работало, либо не помогло), но мой исходный вопрос снова появляется снова:

Есть ли способ изменить время ожидания или как-то контролировать полное "неответное" фиаско?

4b9b3361

Ответ 1

Вы можете использовать DisableProcessWindowsGhosting функцию win32:

[DllImport("user32.dll")]
public static extern void DisableProcessWindowsGhosting();

Это фактически не предотвращает замораживание окна, но предотвращает текст "Not Respongind" в заголовке.

Ответ 2

Я боюсь, что самое простое решение - сделать свой собственный CopyToClipboard(), где вы в своем цикле for, время от времени, делаете Application.DoEvents, который поддерживает поток ui.

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

Поскольку вы знаете данные, вы, вероятно, можете сделать гораздо более простую процедуру, чем общий, который использует DevExpress.

вот так:

const int feedbackinterval = 1000;

private void btnCopy_Click(object sender, EventArgs e)
{
    StringBuilder txt2CB = new StringBuilder();
    int[] rows = gridView1.GetSelectedRows();

    if (rows == null) return;

    for (int n = 0; n < rows.Length; n++)
    {
        if ((n % feedbackinterval) == 0) Application.DoEvents();

        if (!gridView1.IsGroupRow(rows[n]))
        {
            var item = gridView1.GetRow(rows[n]) as vWorkOrder;
            txt2CB.AppendLine(String.Format("{0}\t{1}\t{2}",
            item.GroupCode, item.GroupDesc, item.note_no??0));
        }
     }
        Clipboard.SetText(txt2CB.ToString());
}

Ответ 3

Это связано с тем, что вы синхронно вызываете длительный метод в своем основном потоке приложения. Когда ваше приложение занято, оно не отвечает на сообщения из окон и помечается как (Не отвечает) до завершения.

Чтобы справиться с этим, сделайте свое копирование асинхронно, например. используя задачу как одно простейшее решение.

Task task = new Task(() =>
        {
            gridView.Enabled = false;
            gridView.CopyToClipboard();
            gridView.Enabled = true;
        });

        task.Start();

Отключите свою сетку, чтобы никто не мог изменять значения в графическом интерфейсе. Остальная часть вашего приложения остается отзывчивой (может иметь побочные эффекты!).

Ответ 4

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

 Process proc = new Process();
 proc.StartInfo.FileName = "<Your Program>.exe"

 proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

Edit: Вы также можете создать событие таймера, наблюдая за другим процессом и перевернув свою собственную логику тайм-аута

    DateTime dStartTime = DateTime.Now;
    TimeSpan span = new TimeSpan(0, 0, 0);
    int timeout = 30; //30 seconds        

    private void timer1_Tick(Object myObject, EventArgs myEventArgs)
    {
        while (span.Seconds < timeout)
        {
            Process[] processList = Process.GetProcessesByName("<YourProcess.exe>");
            if (processList.Length == 0)
            {
                //process completed
                timer1.Stop();
                break;
            }
            span = DateTime.Now.Subtract(dStartTime);
        }
        if (span.Seconds > timeout)
        {
            Process[] processList = Process.GetProcessesByName("<YourProcess.exe>");

            //Give it one last chance to complete
            if (processList.Length != 0)
            {
                //process not completed
                foreach (Process p in processList)
                {
                    p.Kill();
                }
            }
            timer1.Stop();
        }
    }

Edit2

Вы можете использовать pInvoke "ShowWindow", чтобы выполнить скрытие и отображение окна после его запуска

private const int SW_HIDE = 0x00;
private const int SW_SHOW = 0x05;

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

Ответ 5

Существует несколько возможных подходов

  • Скрыть основную форму за период операции
  • Как-то клонировать/сериализовывать элемент управления и передавать его в поток с другим диспетчером пользовательского интерфейса
  • Получить выделенные ячейки через gridView.GetSelectedCells(), а затем асинхронно поместить их содержимое в буфер обмена

Было бы полезно, если бы вы загрузили библиотеку GridView где-нибудь, чтобы мы могли заглянуть внутрь.

Ответ 6

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

Если вам необходимо увидеть приложение и для него, как представляется, работать, можете ли вы сегментировать свою функцию "копировать в буфер обмена", которая имеет резьбу и принимает либо массив, либо gridview, и диапазон индексов. Преимущество этого заключается в том, что ваш основной поток вашего подчиненного процесса никогда не будет висеть. Недостатком является то, что люди не любят работать с потоками и делегатами на С#.

Ответ 7

Хорошо, "Не реагировать" и артефакты в окнах, которые вы описали, являются лишь симптомами длительной работы в потоке пользовательского интерфейса. Поток пользовательского интерфейса заблокирован, поэтому пользовательский интерфейс заблокирован. Этого не избежать. Честно говоря, просто "повезло", что ваше приложение выглядит так же отзывчиво, как и оно.

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

Спросите себя: действительно ли моим пользователям нужно скопировать все строки из этого представления? Можно ли каким-либо образом фильтровать данные для ограничения строк? Если нет, существует свойство MaxRowCopyCount, которое ограничивает количество копируемых строк - может ли это быть использовано без нарушения рабочего процесса?

Наконец, если все остальное не работает, есть ли какой-либо другой носитель, который вы можете использовать (возможно, промежуточный файл), к которому данные могут быть скопированы в фоновом потоке?

Ответ 8

Тайм-аут, задокументированный в IsHungAppWindow, не может быть изменен. Не используйте глобальное состояние для управления локальной проблемой.

Вы должны оптимизировать часть, которая вызывает невосприимчивость. Например, используйте кеширование, виртуальную сетку (DevExpress называет его "режимом сервера" ), пейджинг, делегирует сортировку фильтру ibindinglistview, который выполняет запрос базы данных (использует индекс базы данных) вместо сортировки в памяти (без индексирования) или реализовать IAsyncOperation в ваших данных буфера обмена, поэтому вам нужно будет всего лишь заполнить данные, когда пользователь сделает пасту.