Vb.net Net允许一定的时间来完成一项任务

Vb.net Net允许一定的时间来完成一项任务,vb.net,multithreading,timer,backgroundworker,Vb.net,Multithreading,Timer,Backgroundworker,我试图给我的程序一定的时间,在它失败之前与远程驱动器建立连接,但我很难理解可用的不同选项。我试过定时器之类的,但程序仍然挂在与数据库联系的部分。我已经研究并阅读了我需要运行一个后台工作程序,或者在另一个线程中运行它,但这超出了我目前的理解 以下是我目前掌握的情况: Public Sub Initialise_View() Dim I As Integer = 0 Dim Fault As Boolean = False Main.VIEW_

我试图给我的程序一定的时间,在它失败之前与远程驱动器建立连接,但我很难理解可用的不同选项。我试过定时器之类的,但程序仍然挂在与数据库联系的部分。我已经研究并阅读了我需要运行一个后台工作程序,或者在另一个线程中运行它,但这超出了我目前的理解

以下是我目前掌握的情况:

    Public Sub Initialise_View()
        Dim I As Integer = 0
        Dim Fault As Boolean = False
        Main.VIEW_SavingMessage.Visible = False

        Main.VIEW_Title.Text = "Establishing Connecion To Database... Please Wait"
        Main.Refresh()

        DataGridView_Setup.Set_Datasource(0) 'This subroutine opens a connection to
    'the database and will pass a fault variable back if the database is not found,
    'however this hangs for ages if the system is having trouble accessing the
    'network drive, upwards of 5mins sometimes!


        If Fault = True Then Main.VIEW_Title.Text = "Error In Connection..."
        Main.Refresh()

    End Sub

What I'd really like is something like:

    If Connection is not established within 30 seconds Then
         Msgbox "Error, Unable to establish connection"
         Exit Sub
    End If

Which would be easy, using a timer, as long as the program didn't hang when trying to actually connect.

So my question is, is there any way around this? If so, what's the best way of going about it?

TIA

**Update**

Following Answers, I have updated to the following:

Imports System.Threading

Module View_Initialise
    Public t1 As Threading.Thread
    Public Sub Initialise_View()
        Main.Timer1.Interval = 20 * 1000
        Main.Timer1.Start()

        t1 = New Thread(New ThreadStart(AddressOf Run_Datasource))
        t1.Start()

    End Sub

    Public Sub Run_Datasource()
        Dim I As Integer = 0
        Dim Fault As Boolean = False
        Main.VIEW_SavingMessage.Visible = False

        Main.VIEW_Title.Text = "Establishing Connecion To Database... Please Wait"
        Main.Refresh()

        DataGridView_Setup.Set_Datasource(0)
        DataGridView_Setup.BindingUpdates()

        If Fault = True Then Main.VIEW_Title.Text = "Error In Connection..."
        Main.Refresh()
    End Sub



End Module
这似乎起作用了,因为它确实触发了所有代码ect,但是
Set\u Datasource(0)
例程没有正确触发,在告诉用户表单使用信息更新的部分代码中,这没有发生。这是来自
Set\u数据源(0)
的代码:(对不起,太长了)

如上代码所述,错误似乎是新线程无法访问表单中的信息


谢谢。

您需要将连接子程序作为新线程运行。线程的一个常见示例是:

首先创建新线程:

Public t1 As Threading.Thread
现在从函数调用线程

Private Sub Initialise_View()
    'Run your connecting Sub-Routine
    t1 = New Thread(New ThreadStart(AddressOf Set_Datasource))
    t1.Start()
End sub
现在连接子程序

Sub Set_Datasource()
    'Your code here
End sub 
现在你的应用程序不会挂断

同时,您可以启动计时器,让它在30秒后关闭连接,现在关闭线程,然后显示您的错误

我需要运行一个后台工作程序,或者在另一个线程中运行它,但这超出了我目前的理解

事实上,一旦你正确理解了这个概念,背景工作人员就非常直截了当了。它们实际上只是第二个线程,包装在一个开箱即用的优化类中,已经包含了在不冻结主线程的情况下完成任务所需的方法

我已经多次使用过的一个简单实现如下所示:

Imports System.ComponentModel

Public Class BGWexample
    Sub MainProgram()
        '   delcare your bgWoker-object
        Dim BgWorker As BackgroundWorker

        '   initialization and basic setup of your bgWorker
        BgWorker = New BackgroundWorker()
        BgWorker.WorkerReportsProgress = False
        BgWorker.WorkerSupportsCancellation = False

        '   tell the bgWorker where it will find the code for it's already implemented methods
        AddHandler BgWorker.DoWork, AddressOf BgWorkerDoesHisThing
        AddHandler BgWorker.RunWorkerCompleted, AddressOf BgWorkerHasFinished

        '   to start your background thread, just execute the bgWoker by calling its .RunWorkerAsync-method instead of calling your already implemented method to load your data from the database
        BgWorker.RunWorkerAsync()
    End Sub

    Private Sub BgWorkerDoesHisThing(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        '   this will host the code to load the data from the database, e.g. declaration of your Data-Access-Object, querying, populating DataTables etc.
    End Sub

    Private Sub BgWorkerHasFinished(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        '   use this method to hide any loading screens, enable some controls etc.
    End Sub
End Class
只需将
Set_数据源(模式为整数)
的代码放入
bgworkerdoeshithing()
-方法中,并执行
BgWorker.RunWorkerAsync()
方法,而不是
Set_数据源(模式为整数)
-方法

这将导致BgWorker通过在声明块中添加相应的处理程序来执行已附加到
.DoWork
-事件的
bgWorkerDoeshithing()
-Sub

请注意:如果要从后台线程与GUI交互,使用后台线程会有点棘手

在本例中,
bgWorkerDoeshithing()
-Sub作为不同的线程在中执行,不允许修改主线程的GUI控件,而
BgWorkerHasFinished()
-Sub将在主线程中再次执行,这意味着它再次具有对GUI控件的完全访问权限

所以现在,我建议将GUI放入加载屏幕,并将加载屏幕隐藏在
BgWorkerHasFinished()
-方法中


请记住,如果主线程取决于后台线程的结果,而不是等待它完成其工作,那么您可能会遇到错误。这就是
BackgroundWorker.RunWorkerCompleted
-事件的目的,这也是我向该事件添加事件处理程序的原因,它将在BgWorker完成其工作后立即执行专用的
BgWorkerHasFinished()
-方法。

Hmm,这似乎是试图触发代码,但是当
Set\u数据源
子运行时,它现在不会更新表单。我将更新我的问题,以表明我的答案在某种程度上有所进展。我已经设法让后台工作人员填充数据集,但是当涉及到更新主要表单项时,系统由于问题中描述的相同问题而崩溃curr=Main.DataGridView1.CurrentRow`失败,因为在Datagrid中找不到当前行(因为Datagrid不会由后台工作程序填充)。因此,我尝试填充一个公共数据集,然后在主表单代码中填充Datagrid,但仍然失败,出现了同样的问题。有什么想法吗?因为您的BackgroundWorker使用的线程不是GUI控件,所以不允许直接与GUI交互。这些调用将非常不稳定,因为BGW线程无法确定GUI对象在特定时间的状态。这是因为BGW线程与主(GUI)线程异步运行。要与GUI交互,请使用GUIs-method。是否确保在DataGridView正确填充行后执行
curr=Main.DataGridView1.CurrentRow
?为此,将从数据库获取数据后需要运行的所有代码(如在DataGridView中显示数据并访问某个DataRow)放入
BgWorkerHasFinished()
-方法中。您的代码的结构应该如下:
BgWorkerDoesHisThing()
-->从数据库中提取数据
BgWorkerHasFinished()
-->填充DataGridView;访问某一行。
Imports System.ComponentModel

Public Class BGWexample
    Sub MainProgram()
        '   delcare your bgWoker-object
        Dim BgWorker As BackgroundWorker

        '   initialization and basic setup of your bgWorker
        BgWorker = New BackgroundWorker()
        BgWorker.WorkerReportsProgress = False
        BgWorker.WorkerSupportsCancellation = False

        '   tell the bgWorker where it will find the code for it's already implemented methods
        AddHandler BgWorker.DoWork, AddressOf BgWorkerDoesHisThing
        AddHandler BgWorker.RunWorkerCompleted, AddressOf BgWorkerHasFinished

        '   to start your background thread, just execute the bgWoker by calling its .RunWorkerAsync-method instead of calling your already implemented method to load your data from the database
        BgWorker.RunWorkerAsync()
    End Sub

    Private Sub BgWorkerDoesHisThing(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        '   this will host the code to load the data from the database, e.g. declaration of your Data-Access-Object, querying, populating DataTables etc.
    End Sub

    Private Sub BgWorkerHasFinished(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        '   use this method to hide any loading screens, enable some controls etc.
    End Sub
End Class