我必须在UI线程运行长时间运行的方法。 (Devex - gridView.CopyToClipboard()
我不需要用户界面,同时复制到响应和我加了一个闪屏,使用户不会闷出了主意。
当我运行这个程序,一切都很好。
当我运行一个不同的程序,依次启动一个新的进程并运行该程序就可以了麻烦开始。 复制标题的几秒钟后读取(无响应)和鼠标光标显示为忙碌,这当然是清除了几秒钟之内,但我想摆脱它,因为它使用户误解的感觉,程序故障。
有什么办法来设置“超时”的过程我创建的?
编辑:
主程序调用下面的代码:
fillsProcess = new Process();
fillsProcess.StartInfo.FileName = Application.ExecutablePath;
fillsProcess.Start();
在fillsProcess,点击某个按钮时,下面的代码被称为:
gridViewToCopy.CopyToClipboard();
这行代码需要一段时间来处理,几秒钟后,fillsProcess的窗口看上去没有反应,因为这种方法在UI线程上运行..
编辑第二:
显然,(真的很理解)
gridViewToCopy.CopyToClipboard();
是不是造成这个问题的唯一方法。 许多Devex方法必须在UI线程上运行(例如,数据的排序,过滤数据)
所以,感谢的人谁提出了具体的解决方案(无论是工作或没有),但我原来的问题弹出右后卫再升:
有没有什么办法来改变超时时间或以某种方式控制整个“没有响应”的惨败?
Answer 1:
您可以使用DisableProcessWindowsGhosting
Win32函数:
[DllImport("user32.dll")]
public static extern void DisableProcessWindowsGhosting();
其实,这并不阻止窗口冻结,但禁止在标题中的“不Respongind”文本。
Answer 2:
恐怕最简单的办法就是让自己CopyToClipboard()
您在您的循环,每一个现在,然后,做一个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());
}
Answer 3:
这是因为你在你的主应用程序线程同步调用长时间运行的方法。 当你的一个应用是忙不来的消息从窗户回应并标记为(无响应),直到完成。
为了解决这个问题做你的异步复制例如使用任务作为一个简单的解决方案。
Task task = new Task(() =>
{
gridView.Enabled = false;
gridView.CopyToClipboard();
gridView.Enabled = true;
});
task.Start();
禁用您的网格,因此没有人能在GUI中更改数值。 你的应用程序的其余部分保持响应(5月有副作用!)。
Answer 4:
你可以开始隐藏的进程,然后检查是否响应,并把它带回眼帘完成后....闪屏会显示其仍然是“响应”。
Process proc = new Process();
proc.StartInfo.FileName = "<Your Program>.exe"
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
编辑:您还可以创建一个定时器事件看其他进程,并推出自己的超时逻辑
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);
Answer 5:
有几种可能的方法
- 隐藏操作的周期的主要形式
- 不知怎的,克隆/序列化的控制,并将其与另一个UI调度员传递给一个线程
- 通过获取选定单元格
gridView.GetSelectedCells()
然后把它们的内容到剪贴板异步
这将是更有帮助,如果你所上传的GridView
库的地方,这样我们就可以看看。
Answer 6:
我不清楚你的用户是否需要一看就知道是“反应迟钝”的画面。 如果没有必要,你可以尝试让应用程序运行在此应用程序的主线程后的背景是封闭的; 或者你可以最小化的应用程序。
如果有必要查看应用程序,并为它似乎是工作,你能细分“复制到剪贴板”,即有螺纹,发生在数组或GridView和索引范围等功能。 其优点是,你对你的下属进程的主线程永远不会挂起。 它的缺点是人们不喜欢用线程和代表在C#中工作。
Answer 7:
好吧,在“没有响应”和窗口你所描述伪像只是在你的UI线程上运行一个长期活动的症状。 在UI线程被阻塞,所以UI被冻结。 有没有避免这种。 说实话,这只是“幸运”你的应用程序显示为它的响应。
至于我可以看到,这里已经描述了每一个解决办法就是捏造,你的UI线程被冻结的事实黑客。 不要这样做。 修正你的程序,以便在UI线程不会冻结。
问问自己:我的用户真正需要的所有行从该视图复制? 可以将数据以某种方式限制行进行过滤? 如果不是,有一个叫MaxRowCopyCount属性这限制了被复制的行数 - 可以这样不会破坏您的工作流程杠杆?
最后,如果一切都失败了,有没有可以用一些其他媒体(可能是中间文件),哪些数据可以在后台线程被复制?
Answer 8:
超时,在IsHungAppWindow记录,不能更改。 不要使用全局状态来管理当地的问题。
你必须优化,导致反应迟钝的一部分。 例如使用缓存,虚拟网格(DevExpress的称之为“服务器模式”),寻呼,授分拣到ibindinglistview滤波器,做了数据库查询(使用数据库的索引)而不是在内存中的排序(没有索引)或实施上IAsyncOperation你的剪贴板内容 ,所以你只需要在用户不糊来填充数据。
文章来源: “Not Responding” in window title when running in new process