同步线程会禁用我的应用程序工具 [英] Synchronizing Threads disables my application's tools

查看:36
本文介绍了同步线程会禁用我的应用程序工具的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用同步线程,但是当线程启动时我无法点击我的应用程序上的anthing ...但我需要在应用程序上做一些工作,即使线程计时器已打开,所以怎么能我这样做了吗?



请注意我在vs 2010上使用vb.net



这里是我的代码:



 私人 共享线程作为  System.Threading.AutoResetEvent( False 

私有 Sub start_btn_Click( sender As System。 Object ,e As System.EventArgs)句柄 start_btn.Click
StartTask()
结束 Sub

Sub StartTask()
Dim Tpool As System.Threading.ThreadPool
Dim arg 作为 字符串 = SomeArg
ThreadPool.QueueUserWorkItem( New System.Threading.WaitCallback(_
AddressOf 任务),arg)' 将任务排队。
thread.WaitOne( )' 等待线程调用Set。
writeMsg( 线程完成。 at list_rpt
StartTask()
结束 Sub

Sub 任务( ByVal Arg 作为 对象
writeMsg( 线程从 list_rpt
System.Threading.Thread.Sleep( 4000 ' 等待4秒。
DoWork()
结束 Sub

公开 Sub DoWork()
MTProcessTable = selectMtProcess()
mtCount = MTProcessTable.Row s.Count
writeMsg(mtCount& <中选择的行span class =code-string> list_rpt)

对于 每个 row 作为 DataRow MTProcessTable.Rows
process = Process_class
process.id = row( mt_id
process.mo = row( mt_mo
流程.mt = row( mt_mt
process.datain = row( mt_datain

keyid = validateKey(process.datain)
MOTable = selectMO(process.mo,process.mt)
moRowNb = MOTable.Rows.Count()
MO = MO_class
如果 moRowNb< ;> 0 然后
MOrow = MOTable.Rows( 0
MO.newuser = MOrow( newuser
MO.sim_id = MOrow( sim_id
结束 如果
尝试
选择 案例 keyid
案例 1
如果 moRowNb = 0 然后
如果 insertMO(process.mo,process.mt)然后
writeMsg( 1 MO插入/更新为 rpt_txt
message = msgTable.Rows( 0 )( 1 )。ToString()
MsgBox(消息)
否则
writeMsg ( 1 MO无法插入 rpt_txt
结束 如果
结束 如果
案例 2
如果 moRowNb = 0 那么
writeMsg( 1进程,MO未激活,数据'是', rpt_txt
message = msgTable.Rows( 7 )( 1 )。ToString()
MsgBox(消息)
结束 如果
Catch ex As 异常
logFile( executeTimer ----& ex.Message)
updateProcessed(process.id,ex.Message, 10
最后
updateProcessed(process.id,message, 1
结束 尝试
下一步
thread。设置()
结束 Sub

解决方案

不要这样做:

 ThreadPool.QueueUserWorkItem( System.Threading.WaitCallback(_ 
AddressOf 任务),arg) ' 将任务排队。
thread.WaitOne()' 等待线程进行校准l设置。



要生成一个新线程,然后立即等待该线程在启动它的线程上完成它就像没有线程一样所有。您也可以在按钮点击事件中完成任务中的所有工作。



您想要线程做它的工作然后通知回启动它的线程(可能在工作完成时通知状态更新)。



你是什么在您的应用程序中执行的是UI线程上的 WaitOne ,如果这样做,您的UI将锁定直到通知事件,这很糟糕。



如果您刚开始使用多线程应用程序,请查看使用 BackgroundWorker ,这些事件可以挂钩到完成状态更新和任务完成时的报告。



这样的事可能对你有用:

 Imports System.Threading 
Imports System.ComponentModel

Public Class Form1

Private Sub startButton_Click(sender As System.Object,e As System.EventArgs)处理startButton。社区法网k
Dim worker As New BackgroundWorker()

worker.WorkerSupportsCancellation = True
worker.WorkerReportsProgress = True

AddHandler worker.DoWork,AddressOf MyLongRunningOperation
AddHandler worker.ProgressChanged,AddressOf MyProgressUpdate
AddHandler worker.RunWorkerCompleted,AddressOf MyWorkHereIsDone

worker.RunWorkerAsync()
End Sub

Sub MyLongRunningOperation (sender As Object,e As DoWorkEventArgs)
Dim worker As BackgroundWorker = CType(sender,BackgroundWorker)

For i = 0 To 10
if worker.CancellationPending Then
e.Cancel = True
退出
结束如果
'做你的工作
Thread.Sleep(1000)
worker.ReportProgress(i * 10)
Next
End Sub

Private Sub MyProgressUpdate(ByVal sender A s Object,ByVal e As ProgressChangedEventArgs)
progressBar.Value = e.ProgressPercentage
statusText.Text = e.ProgressPercentage& %complete
End Sub

Private Sub MyWorkHereIsDone(ByVal sender As Object,ByVal e As RunWorkerCompletedEventArgs)
如果e.Cancelled = True则
completedText.Text =操作被取消了!
ElseIf e.Error IsNot Nothing然后
completedText.Text =操作失败:& e.Error.Message
否则
completedText.Text =我已经完成了!
结束如果
结束子

结束等级





它依赖于 progressBar statusText completedText 在您的表单上。我没有连接取消按钮,但我认为应该是自我解释。



希望这会有所帮助,

Fredrik


i'm using Synchronizing Threads but when the thread is starting i'm not able to click on anthing on my application... but i need to do some work on the app even if the thread timer is on so how can i do that?

note that i'm using vb.net on vs 2010

here is my code:

Private Shared thread As New System.Threading.AutoResetEvent(False) 

Private Sub start_btn_Click(sender As System.Object, e As System.EventArgs) Handles start_btn.Click
    StartTask()
End Sub

Sub StartTask()
    Dim Tpool As System.Threading.ThreadPool
    Dim arg As String = "SomeArg"
    ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback( _
       AddressOf Task), arg)  ' Queue a task.
    thread.WaitOne() ' Wait for the thread to call Set.
    writeMsg("Thread is done. at ", "list_rpt")
    StartTask()
End Sub

Sub Task(ByVal Arg As Object)
    writeMsg("Thread is starting at ", "list_rpt")
    System.Threading.Thread.Sleep(4000) ' Wait 4 seconds.
    DoWork()
End Sub

Public Sub DoWork()
    MTProcessTable = selectMtProcess()
    mtCount = MTProcessTable.Rows.Count
    writeMsg(mtCount & " rows selected at ", "list_rpt")

    For Each row As DataRow In MTProcessTable.Rows
        process = New Process_class
        process.id = row("mt_id")
        process.mo = row("mt_mo")
        process.mt = row("mt_mt")
        process.datain = row("mt_datain")

        keyid = validateKey(process.datain)
        MOTable = selectMO(process.mo, process.mt)
        moRowNb = MOTable.Rows.Count()
        MO = New MO_class
        If moRowNb <> 0 Then
            MOrow = MOTable.Rows(0)
            MO.newuser = MOrow("newuser")
            MO.sim_id = MOrow("sim_id")
        End If
        Try
            Select Case keyid
                Case 1
                    If moRowNb = 0 Then
                        If insertMO(process.mo, process.mt) Then
                            writeMsg("1 MO inserted/updated at ", "rpt_txt")
                            message = msgTable.Rows(0)(1).ToString()
                            MsgBox(message)
                        Else
                            writeMsg("1 MO could not be inserted at ", "rpt_txt")
                         End If
                   End if
                Case 2
                    If moRowNb = 0 Then
                        writeMsg("1 process with MO not active and datain 'yes' at ", "rpt_txt")
                        message = msgTable.Rows(7)(1).ToString()
                        MsgBox(message)
                    End if
        Catch ex As Exception
            logFile("executeTimer ----" & ex.Message)
            updateProcessed(process.id, ex.Message, 10)
        Finally
            updateProcessed(process.id, message, 1)
        End Try
    Next row
    thread.Set()
End Sub

解决方案

Don't do things like this:

ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback( _
   AddressOf Task), arg)  ' Queue a task.
thread.WaitOne() ' Wait for the thread to call Set.


To spawn a new thread and then immediately wait for that thread to finish on the thread that started it is the same as not threading it at all. You might as well do all of the work in Task in the button click event.

You want the thread to do it's work and then notify back to the thread that started it (possibly with status updates being notified back as the work is being done).

What you're doing in your application is a WaitOne on the UI thread, if you do that your UI will lock until the event is notified, this is bad.

If you're just starting out with multithreading your application, look into using the BackgroundWorker, that comes with events that you can hook into to do things like status updates and report when task is completed.

Something like this might work for you:

Imports System.Threading
Imports System.ComponentModel

Public Class Form1

    Private Sub startButton_Click(sender As System.Object, e As System.EventArgs) Handles startButton.Click
        Dim worker As New BackgroundWorker()

        worker.WorkerSupportsCancellation = True
        worker.WorkerReportsProgress = True

        AddHandler worker.DoWork, AddressOf MyLongRunningOperation
        AddHandler worker.ProgressChanged, AddressOf MyProgressUpdate
        AddHandler worker.RunWorkerCompleted, AddressOf MyWorkHereIsDone

        worker.RunWorkerAsync()
    End Sub

    Sub MyLongRunningOperation(sender As Object, e As DoWorkEventArgs)
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)

        For i = 0 To 10
            If worker.CancellationPending Then
                e.Cancel = True
                Exit For
            End If
            ' Do your work
            Thread.Sleep(1000)
            worker.ReportProgress(i * 10)
        Next
    End Sub

    Private Sub MyProgressUpdate(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
        progressBar.Value = e.ProgressPercentage
        statusText.Text = e.ProgressPercentage & "% complete"
    End Sub

    Private Sub MyWorkHereIsDone(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        If e.Cancelled = True Then
            completedText.Text = "Operation was cancelled!"
        ElseIf e.Error IsNot Nothing Then
            completedText.Text = "Operation failed: " & e.Error.Message
        Else
            completedText.Text = "I am all done!"
        End If
    End Sub

End Class



It relies on progressBar, statusText and completedText being on your form. I haven't wired up a cancel button but that should be self explanatory I think.

Hope this helps,
Fredrik


这篇关于同步线程会禁用我的应用程序工具的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆