vb.net – 创建在另一个线程上运行的进度条,同时在主线程中保持计算

vb.net – 创建在另一个线程上运行的进度条,同时在主线程中保持计算,第1张

概述前言:我知道这是一种不寻常/不正确的方法.我可以用“真正的”ShowDialog(),后台工作者/线程等来做到这一点.我不是那样寻求帮助的;我正在努力做我在这里描述的具体内容,即使它很难看.如果由于X原因这是不可能的,请告诉我. 我为一些长期运行的 *** 作创建了一个奇特的进度对话框.我需要在新线程上显示此对话框,同时在调用(大多数情况下为UI)线程上继续处理. 这有3个真正的要求: >阻止用户与调用表 前言:我知道这是一种不寻常/不正确的方法.我可以用“真正的”ShowDialog(),后台工作者/线程等来做到这一点.我不是那样寻求帮助的;我正在努力做我在这里描述的具体内容,即使它很难看.如果由于X原因这是不可能的,请告诉我.

我为一些长期运行的 *** 作创建了一个奇特的进度对话框.我需要在新线程上显示此对话框,同时在调用(大多数情况下为UI)线程上继续处理.

这有3个真正的要求:

>阻止用户与调用表单交互(类似于ShowDialog(this))
>将进度对话框保持在主窗口上方(现在可能落后)
>允许主线程继续处理

我看起来像这样(到目前为止工作得很好,就运行而言,除了上面的那些问题):

Using ... ShowNewProgressDialogonNewThread() ...      Logic      UpdateProgress() //static      Logic      UpdateProgress() //static,uses Invoke() to call dialog      ...End Using  // destroys the form,etc

我尝试了几种方法来做到这一点:

> BackgrounDWorker / Thread上的ShowDialog()
> Action.BeginInvoke()调用一个函数
> ProgressForm.BeginInvoke(…调用ShowDialog的方法……)
>在实现IWin32Window的类中包装main表单,因此它可以被称为交叉线程并传递给ShowDialog() – 这个稍后在某个地方失败了,但至少会导致ShowDialog()不立即barf.

关于如何使这项工作的任何线索或智慧?

解决方案(现在)

>对EnableWindow的调用正是我所寻求的.
>我根本没有遇到任何崩溃
>更改为使用ManualresetEvent
>我设置了topMost,因为我不能总是保证表格会最终排在最前面.也许有更好的方法.
>我的进度表格就像一个闪屏(没有大小,没有工具栏等),也许是因为缺少崩溃(在回答中提到)
>这里是another thread on the EnableWindow topic(没有参考此修复,tho)

解决方法 在(死)表单上始终显示进度窗口是困难的要求.这通常通过使用Form.Show(所有者)重载来处理.它会给你的情况带来麻烦,WF不会欣赏属于另一个线程的所有者表单.这可以通过P / Invoking SetwindowLong()来设置所有者.

但是现在出现了一个新问题,一旦尝试向其所有者发送消息,进度窗口就会逐渐消失.有点令人惊讶的是,当您使用Invoke()而不是BeginInvoke()来更新进度时,这个问题有点消失.有点,您仍然可以通过将鼠标移动到禁用所有者的边框上来解决问题.实际上,你必须使用topMost来确定Z顺序.更现实的是,windows不支持您尝试做的事情.你知道真正的解决方案,它是你问题的首要问题.

这是一些要试验的代码.假设你的进度形式叫做dlgProgress:

imports System.ThreadingPublic Class ShowProgress  Implements Idisposable  Private Delegate Sub UpdateProgressDelegate(ByVal pct As Integer)  Private mOwnerHandle As IntPtr  Private mOwnerRect As Rectangle  Private mProgress As dlgProgress  Private mInterlock As ManualresetEvent  Public Sub New(ByVal owner As Form)    DeBUG.Assert(owner.Created)    mOwnerHandle = owner.Handle    mOwnerRect = owner.Bounds    mInterlock = New ManualresetEvent(False)    Dim t As Thread = New Thread(AddressOf dlgStart)    t.SetApartmentState(ApartmentState.STA)    t.Start()    mInterlock.WaitOne()  End Sub  Public Sub dispose() Implements Idisposable.dispose    mProgress.BeginInvoke(New MethodInvoker(AddressOf dlgClose))  End Sub  Public Sub UpdateProgress(ByVal pct As Integer)    mProgress.Invoke(New UpdateProgressDelegate(AddressOf dlgUpdate),pct)  End Sub  Private Sub dlgStart()    mProgress = New dlgProgress    mProgress.Startposition = FormStartposition.Manual    mProgress.ShowInTaskbar = False    AddHandler mProgress.Load,AddressOf dlgLoad    AddHandler mProgress.FormClosing,AddressOf dlgClosing    EnableWindow(mOwnerHandle,False)    SetwindowLong(mProgress.Handle,-8,mOwnerHandle)    Application.Run(mProgress)  End Sub  Private Sub dlgLoad(ByVal sender As Object,ByVal e As EventArgs)    mProgress.Location = New Point( _      mOwnerRect.left + (mOwnerRect.WIDth - mProgress.WIDth) \ 2,_      mOwnerRect.top + (mOwnerRect.Height - mProgress.Height) \ 2)    mInterlock.Set()  End Sub  Private Sub dlgUpdate(ByVal pct As Integer)    mProgress.Progressbar1.Value = pct  End Sub  Private Sub dlgClosing(ByVal sender As Object,ByVal e As FormClosingEventArgs)    EnableWindow(mOwnerHandle,True)  End Sub  Private Sub dlgClose()    mProgress.Close()    mProgress = nothing  End Sub  '--- P/Invoke  Public Shared Function SetwindowLong(ByVal hWnd As IntPtr,ByVal nIndex As Integer,ByVal DWNewLong As IntPtr) As IntPtr    If IntPtr.Size = 4 Then      Return SetwindowLongPtr32(hWnd,nIndex,DWNewLong)    Else      Return SetwindowLongPtr64(hWnd,DWNewLong)    End If  End Function  Private Declare Function EnableWindow lib "user32.dll" (ByVal hWnd As IntPtr,ByVal enabled As Boolean) As Boolean  Private Declare Function SetwindowLongPtr32 lib "user32.dll" Alias "SetwindowLongW" (ByVal hWnd As IntPtr,ByVal DWNewLong As IntPtr) As IntPtr  Private Declare Function SetwindowLongPtr64 lib "user32.dll" Alias "SetwindowLongW" (ByVal hWnd As IntPtr,ByVal DWNewLong As IntPtr) As IntPtrEnd Class

样品用法:

Private Sub button1_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles button1.Click    Using dlg As New ShowProgress(Me)      For ix As Integer = 1 To 100        dlg.UpdateProgress(ix)        System.Threading.Thread.Sleep(50)      Next    End Using  End Sub
总结

以上是内存溢出为你收集整理的vb.net – 创建在另一个线程上运行的进度条,同时在主线程中保持计算全部内容,希望文章能够帮你解决vb.net – 创建在另一个线程上运行的进度条,同时在主线程中保持计算所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1239518.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存