Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 后台线程锁定UI中的大量磁盘I/O_.net_Multithreading_Backgroundworker_Async Await - Fatal编程技术网

.net 后台线程锁定UI中的大量磁盘I/O

.net 后台线程锁定UI中的大量磁盘I/O,.net,multithreading,backgroundworker,async-await,.net,Multithreading,Backgroundworker,Async Await,在针对230MB数据库的SqlCeEngine.Upgrade()调用过程中,我得到了大量的磁盘I/O—正如预期的那样 问题是,即使它在BackgroundWorker线程中运行,它仍然会锁定UI。我尝试了Async/Await但没有成功。(FWIW,如果时间允许,我将升级代码。) 我要用这个把头发拔出来。我需要在运行时显示一个不确定的进度条,但不管我做什么,进度条都会在中途冻结。我能想到的唯一解决方案是在一个完全独立的过程中进行升级,这当然是相当困难的。如果有必要,我会的 下面是摘录的代码 有

在针对230MB数据库的
SqlCeEngine.Upgrade()
调用过程中,我得到了大量的磁盘I/O—正如预期的那样

问题是,即使它在
BackgroundWorker
线程中运行,它仍然会锁定UI。我尝试了
Async/Await
但没有成功。(FWIW,如果时间允许,我将升级代码。)

我要用这个把头发拔出来。我需要在运行时显示一个不确定的进度条,但不管我做什么,进度条都会在中途冻结。我能想到的唯一解决方案是在一个完全独立的过程中进行升级,这当然是相当困难的。如果有必要,我会的

下面是摘录的代码

有什么想法吗

Friend Class MainForm
  Private Sub itmRestore_Click(Sender As Object, e As EventArgs) Handles itmRestore.Click
    If Utils.MsgQuestion(Bl.Messages.DB_RESTORE_PROMPT) = MsgBoxResult.Yes Then
      ofdRestore.InitialDirectory = Bl.Registry.DownloadFolder
      ofdRestore.FileName = String.Empty

      If ofdRestore.ShowDialog = Windows.Forms.DialogResult.OK Then
        prgCopy.SourcePath = ofdRestore.FileName
        prgCopy.TargetPath = Db.Utils.DatabasePath
        prgCopy.ActionText = "Restoring the database..."

        Me.Cursor = Cursors.WaitCursor
        bgwBackup.RunWorkerAsync(Bl.BackgroundJobs.RestoreDatabase)
      End If
    End If
  End Sub

  Private Sub bgwBackup_DoWork(Sender As Object, e As DoWorkEventArgs) Handles bgwBackup.DoWork
    bgwStartup.ReportProgress(-1, "Loading...")

    Select Case DirectCast(e.Argument, Bl.BackgroundJobs)
      Case Bl.BackgroundJobs.BackupDatabase : Bl.Jobs.Database.BackupDatabase(prgCopy, e)
      Case Bl.BackgroundJobs.RestoreDatabase : Bl.Jobs.Database.RestoreDatabase(prgCopy, e)
      Case Bl.BackgroundJobs.CheckDatabaseVersion : Bl.Jobs.Database.CheckDatabaseVersion(e)
      Case Bl.BackgroundJobs.UpgradeDatabase : Bl.Jobs.Database.UpgradeDatabase(e)
      Case Bl.BackgroundJobs.UpdateDatabaseSchema : Bl.Jobs.Database.UpdateDatabaseSchema(Sender, e)
    End Select
  End Sub

  Private Sub bgwBackup_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgwBackup.ProgressChanged
    UpdateProgress(e.ProgressPercentage, e.UserState)
  End Sub

  Private Sub bgwBackup_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgwBackup.RunWorkerCompleted
    Dim eNextJob As Bl.BackgroundJobs
    Dim oManager As Bl.Jobs.Manager

    oManager = e.Result

    If e.Error Is Nothing Then
      Select Case oManager.CurrentJob
        Case Bl.BackgroundJobs.BackupDatabase
          eNextJob = Bl.BackgroundJobs.None
          UpdateProgress(0)
          Utils.MsgInformation(Bl.Messages.DB_BACKUP_SUCCESS.ToFormat(vbCrLf, sfdBackup.FileName))

        Case Bl.BackgroundJobs.RestoreDatabase
          eNextJob = Bl.BackgroundJobs.CheckDatabaseVersion
          UpdateProgress(0)
          Utils.MsgInformation(Bl.Messages.DB_RESTORE_SUCCESS)

        Case Bl.BackgroundJobs.CheckDatabaseVersion
          If oManager.Continue Then
            eNextJob = Bl.BackgroundJobs.UpdateDatabaseSchema
          Else
            eNextJob = Bl.BackgroundJobs.UpgradeDatabase
            Utils.MsgInformation(Bl.Messages.DB_UPGRADE_NOTICE)
            UpdateProgress(-1, "Upgrading the database...")
          End If

        Case Bl.BackgroundJobs.UpgradeDatabase
          eNextJob = Bl.BackgroundJobs.UpdateDatabaseSchema
          UpdateProgress(0)
          Utils.MsgInformation(Bl.Messages.DB_UPGRADE_SUCCESS)

        Case Bl.BackgroundJobs.UpdateDatabaseSchema
          eNextJob = Bl.BackgroundJobs.None

      End Select
    Else
      Utils.MsgCritical(Bl.Messages.DB_RESTORE_ERROR.ToFormat(vbCrLf, e.Error.ToString))
      eNextJob = Bl.BackgroundJobs.None
    End If

    If eNextJob = Bl.BackgroundJobs.None Then
      UpdateProgress(0, "Ready")
      txtLastName.Focus()

      Me.Cursor = Cursors.Default
    Else
      bgwBackup.RunWorkerAsync(eNextJob)
    End If
  End Sub

  Private Sub UpdateProgress(ProgressPercentage As Integer)
    UpdateProgress(ProgressPercentage, String.Empty)
  End Sub

  Private Sub UpdateProgress(ProgressPercentage As Integer, StatusText As String)
    If ProgressPercentage = -1 Then
      If prgProgress.Style <> ProgressBarStyle.Marquee Then
        prgProgress.Style = ProgressBarStyle.Marquee
        prgProgress.Value = 0
      End If
    Else
      prgProgress.Style = ProgressBarStyle.Blocks
      prgProgress.Value = Min(ProgressPercentage, 100)
    End If

    If Trim(StatusText).Length > 0 Then
      lblStatus.Text = StatusText
    End If
  End Sub

End Class

Namespace Bl
  Namespace Jobs
    Friend Class Manager
      Public CurrentJob As BackgroundJobs
      Public [Continue] As Boolean

      Public Sub New(CurrentJob As BackgroundJobs, [Continue] As Boolean)
        Me.CurrentJob = CurrentJob
        Me.Continue = [Continue]
      End Sub
    End Class

    Friend Class Database
      Public Shared Sub CheckDatabaseVersion(e As DoWorkEventArgs)
        e.Result = New Manager(e.Argument, Db.Utils.CheckDatabaseVersion)
      End Sub

      Public Shared Sub UpgradeDatabase(e As DoWorkEventArgs)
        Db.Utils.UpgradeDatabase()
        e.Result = New Manager(e.Argument, True)
      End Sub

      Public Shared Sub UpdateDatabaseSchema(Worker As BackgroundWorker, e As DoWorkEventArgs)
        If Db.Versioning.SchemaVersionStatus = Db.Enums.SchemaVersionStates.Newer Then
          Throw New ApplicationException("An incompatible database version has been detected. A newer version of Matrix is required.")
        Else
          Db.Versioning.UpdateSchema(Worker, e)
          e.Result = New Manager(e.Argument, True)
        End If
      End Sub

      Public Shared Sub BackupDatabase(Copier As ProgressCopy.ProgressCopy, e As DoWorkEventArgs)
        Copier.Start()
        e.Result = New Manager(e.Argument, True)
      End Sub

      Public Shared Sub RestoreDatabase(Copier As ProgressCopy.ProgressCopy, e As DoWorkEventArgs)
        Db.Utils.ArchiveDatabase()
        Copier.Start()
        e.Result = New Manager(e.Argument, True)
      End Sub
    End Class
  End Namespace

  Friend Enum BackgroundJobs
    None
    UpgradeDatabase
    UpdateDatabaseSchema
    ValidateCityCode
    CheckSubscription
    CheckOptionsWizard
    CheckDatabaseVersion
    BackupDatabase
    RestoreDatabase
  End Enum
End Namespace

Namespace Db
  Friend Class Utils
    Public Shared Sub UpgradeDatabase()
      Dim _
        sSource,
        sTarget As String

      sSource = ArchiveDatabase()
      sTarget = DatabasePath

      Try
        With New SqlCeEngine(SqlCe.Connection.ConnectionString(sSource))
          .Upgrade(SqlCe.Connection.ConnectionString(sTarget))
        End With

      Catch ex As Exception
        Throw New ApplicationException(ex.Message, ex)

      End Try
    End Sub

    Public Shared Function ArchiveDatabase() As String
      Dim oFile As FileInfo

      Dim _
        sTarget,
        sNow As String

      Dim _
          oSource, _
          oTarget _
        As DirectoryInfo

      Do
        sNow = Now.ToFileNameString(DateStringOptions.IncludeTime)
        oSource = New DirectoryInfo(DatabaseFolder)
        sTarget = Path.Combine(oSource.FullName, "Deleted {0}".ToFormat(sNow))
        oTarget = New DirectoryInfo(sTarget)
      Loop While oTarget.Exists

      oTarget.Create()

      For Each oFile In oSource.GetFiles
        oFile.MoveTo(Path.Combine(oTarget.FullName, oFile.Name))
      Next

      ArchiveDatabase = Path.Combine(oTarget.FullName, Db.Utils.DatabaseFile)
    End Function
  End Class
End Namespace
Friend类MainForm
私有子itmRestore\u单击(发件人作为对象,e作为事件参数)处理itmRestore。单击
如果Utils.MsgQuestion(Bl.Messages.DB_RESTORE_PROMPT)=MsgBoxResult.Yes则
ofdRestore.InitialDirectory=Bl.Registry.DownloadFolder
ofdrose.FileName=String.Empty
如果ofdRestore.ShowDialog=Windows.Forms.DialogResult.OK,则
prgCopy.SourcePath=ofdRestore.FileName
prgCopy.TargetPath=Db.Utils.DatabasePath
prgCopy.ActionText=“正在恢复数据库…”
Me.Cursor=Cursors.WaitCursor
bgwBackup.RunWorkerAsync(Bl.BackgroundJobs.RestoreDatabase)
如果结束
如果结束
端接头
私有子bgwBackup_DoWork(发送方作为对象,e作为DoWorkEventArgs)处理bgwBackup.DoWork
bgwStartup.ReportProgress(-1,“加载…”)
选择案例DirectCast(例如参数,Bl.BackgroundJobs)
案例Bl.BackgroundJobs.backupdatebase:Bl.Jobs.Database.backupdatebase(prgCopy,e)
案例Bl.BackgroundJobs.RestoreDatabase:Bl.Jobs.Database.RestoreDatabase(prgCopy,e)
案例Bl.BackgroundJobs.CheckDatabaseVersion:Bl.Jobs.Database.CheckDatabaseVersion(e)
案例Bl.BackgroundJobs.UpgradeDatabase:Bl.Jobs.Database.UpgradeDatabase(e)
案例Bl.BackgroundJobs.UpdateDatabaseSchema:Bl.Jobs.Database.UpdateDatabaseSchema(发件人,e)
结束选择
端接头
私有子bgwBackup\u ProgressChanged(发送方作为对象,e作为ProgressChangedEventArgs)处理bgwBackup.ProgressChanged
UpdateProgress(e.ProgressPercentage,e.UserState)
端接头
私有子bgwBackup\u RunWorkerCompleted(发送方作为对象,e作为RunWorkerCompletedEventArgs)处理bgwBackup.RunWorkerCompleted
Dim eNextJob作为Bl.BackgroundJobs
将oManager设置为Bl.Jobs.Manager
oManager=e.结果
如果e.错误不算什么,那么
选择案例oManager.CurrentJob
案例Bl.BackgroundJobs.BackUpdatebase
eNextJob=Bl.BackgroundJobs.None
UpdateProgress(0)
MsgInformation(Bl.Messages.DB_BACKUP_SUCCESS.ToFormat(vbCrLf,sfdBackup.FileName))
案例Bl.BackgroundJobs.RestoreDatabase
eNextJob=Bl.BackgroundJobs.CheckDatabaseVersion
UpdateProgress(0)
Utils.MsgInformation(Bl.Messages.DB\u RESTORE\u SUCCESS)
案例Bl.BackgroundJobs.CheckDatabaseVersion
如果是oManager,则继续
eNextJob=Bl.BackgroundJobs.UpdateDatabaseSchema
其他的
eNextJob=Bl.BackgroundJobs.upgrade数据库
Utils.MsgInformation(Bl.Messages.DB\u升级通知)
UpdateProgress(-1,“升级数据库…”)
如果结束
案例Bl.BackgroundJobs.Upgrade数据库
eNextJob=Bl.BackgroundJobs.UpdateDatabaseSchema
UpdateProgress(0)
Utils.MsgInformation(Bl.Messages.DB\u升级成功)
案例Bl.BackgroundJobs.UpdateDatabaseSchema
eNextJob=Bl.BackgroundJobs.None
结束选择
其他的
Utils.msgccritical(Bl.Messages.DB_RESTORE_ERROR.ToFormat(vbCrLf,e.ERROR.ToString))
eNextJob=Bl.BackgroundJobs.None
如果结束
如果eNextJob=Bl.BackgroundJobs.None,则
UpdateProgress(0,“就绪”)
txtLastName.Focus()
Me.Cursor=Cursors.Default
其他的
bgwBackup.RunWorkerAsync(eNextJob)
如果结束
端接头
私有子UpdateProgress(ProgressPercentage作为整数)
UpdateProgress(ProgressPercentage,String.Empty)
端接头
私有子UpdateProgress(ProgressPercentage为整数,StatusText为字符串)
如果ProgressPercentage=-1,则
如果prgProgress.Style ProgressBarStyle.Marquee,则
prgProgress.Style=ProgressBarStyle.Marquee
prgProgress.Value=0
如果结束
其他的
prgProgress.Style=ProgressBarStyle.Blocks
prgProgress.Value=Min(进度百分比,100)
如果结束
如果修剪(StatusText).Length>0,则
lblStatus.Text=状态文本
如果结束
端接头
末级
名称空间Bl
命名空间作业
朋友班经理
公共作业作为背景作业
公共[继续]为布尔值
Public Sub New(当前作业作为背景作业,[继续]作为布尔值)
Me.CurrentJob=CurrentJob
Me.Continue=[继续]
端接头
末级
好友类数据库
公共共享子检查数据库版本(e作为DoWorkEventArgs)
e、 结果=新管理器(e.Argument,Db.Utils.CheckDatabaseVersion)
端接头
公共共享子升级数据库(如DoWorkEventArgs)
Db.Utils.UpgradeDatabase()
e、 结果=新管理器(例如参数,True)
端接头
公共共享子UpdateDatabaseSchema(Worker作为BackgroundWorker,e作为DoWorkEventArgs)
如果Db.Versioning.schemaversationstatus=Db.Enums.schemaversationstates.Newer,则
抛出新的ApplicationException(“检测到不兼容的数据库版本。需要更新版本的Matrix。”)
其他的
Db.Versioning.UpdateSchema(Worker,e)
e、 结果=新管理器(例如参数,True)
如果结束
端接头
公共共享子备份数据库(复印机为ProgressCopy.ProgressCopy,e为DoWorkEventArgs)
复印机启动
e、 结果=新管理器(例如参数,True)
端接头
公共共享子恢复数据库(复印机为ProgressCo