none
視窗關閉再開問題 RRS feed

  • 問題

  • 請問各位大大,我因懶惰需要,所以寫了一個小程式

    這程式可以正常的執行 第二次點選沒問題

            If (Form2.Created = True) Then
                Form2.Close()
                Form2.Show()
            Else
                Form2.Show()
            End If

    但如果我放在Module裡面

    Module2.Forrmm(Form2)
    Public Sub Forrmm(created As Object)
            If (created.Created = True) Then
                created.Close()
                created.Show()
            Else
                created.Show()
            End If
        End Sub

    執行後 我第二次點選 會跑出
    System.ObjectDisposedException: '無法存取已處置的物件。
    ObjectDisposed_ObjectName_Name'

    請問教各位高手,我的程式碼要如何解決??

    2018年1月3日 上午 03:29

解答

  • 看來你想要做一個單例 Form 顯示管理器, 參考以下程式碼:

    Public Class FormsManager
    
        Private _forms As Dictionary(Of Type, Form)
    
        Private Sub New()
            _forms = New Dictionary(Of Type, Form)
        End Sub
    
        Public Sub Show(type As Type)
            If _forms.ContainsKey(type) Then
                _forms(type).Close()
                _forms.Remove(type)
            End If
            _forms(type) = DirectCast(Activator.CreateInstance(type), Form)
            _forms(type).Show()
        End Sub
    
        Private Shared _instance As FormsManager
        Public Shared ReadOnly Property Instance As FormsManager
            Get
                If _instance Is Nothing Then
                    _instance = New FormsManager()
                End If
                Return _instance
            End Get
        End Property
    
    End Class

    在 Form1 中使用

    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            FormsManager.Instance.Show(GetType(Form2))
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            FormsManager.Instance.Show(GetType(Form2))
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            FormsManager.Instance.Show(GetType(Form3))
        End Sub
    End Class



    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2018年1月3日 下午 01:49
    版主

所有回覆

  • 參考這篇看看。

    https://dotblogs.com.tw/v6610688/2014/05/06/close_form_cannot_access_a_disposed_object

    2018年1月3日 上午 03:41
  • 您貼的網址 似乎是使用 Hide()

    但是我想要同時有刷新頁面的效果 所以我想要用Close()

    2018年1月3日 上午 03:52
  • 這樣試看看:

    Else

    If created.IsDisposed Then

    Dim f As New Form2

    f.Show()

    End If End If


    2018年1月3日 上午 07:20
  • 這問題起源自 Visual Basic 編譯器的一個奇妙特性。

    以你的程式碼來看, Form2 本來是一個 class 的名稱,

    但當你呼叫了 Form2.Show(),就會產生一個在該執行緒的 單例執行個體(其型別為 Form2 Class)

    其實在使用上的最佳建議是 "儘量少用 Form2.Show() 這樣的語法"。

    而是遵循一般正常的方式:

    Dim frm As Form2 = new Form2()

    frm.Show()

    另外,你在參數傳遞的型別上用了 object,這在 Visual Basic 的編譯行為極有可能會出現延遲繫結型別的狀況。建議你可以先把該 object 型別改為 Form ,因為你內容中用到的幾個成員 Created 和 Show() 是定義在 Control class, 但 Close() 是定義在 Form class (Form 是 Control 的子類別)


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2018年1月3日 上午 08:09
    版主
  • TO:tihs

    我看了一下您的程式碼

    我把程式碼改成

    Public Sub Forrmm(created As Form)
            If created.IsDisposed = False Then
                Dim f As New Form2
                f.Close()
                f.Show()
            Else
                Dim f As New Form2
                f.Show()
            End If
        End Sub

    還是一樣跑出問題視窗

    2018年1月3日 下午 12:06
  • 謝謝您給我這方面的知識

    我參考了您的程式碼

    我事者改成

    Public Sub Forrmm(created As Form) created = New Form2() If created.Created = True Then created.Close() created.Show() Else created.Show() End If End Sub

    但是 視窗會越開越多 我想因該是因為New的關西

    2018年1月3日 下午 12:13
  • 看來你想要做一個單例 Form 顯示管理器, 參考以下程式碼:

    Public Class FormsManager
    
        Private _forms As Dictionary(Of Type, Form)
    
        Private Sub New()
            _forms = New Dictionary(Of Type, Form)
        End Sub
    
        Public Sub Show(type As Type)
            If _forms.ContainsKey(type) Then
                _forms(type).Close()
                _forms.Remove(type)
            End If
            _forms(type) = DirectCast(Activator.CreateInstance(type), Form)
            _forms(type).Show()
        End Sub
    
        Private Shared _instance As FormsManager
        Public Shared ReadOnly Property Instance As FormsManager
            Get
                If _instance Is Nothing Then
                    _instance = New FormsManager()
                End If
                Return _instance
            End Get
        End Property
    
    End Class

    在 Form1 中使用

    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            FormsManager.Instance.Show(GetType(Form2))
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            FormsManager.Instance.Show(GetType(Form2))
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            FormsManager.Instance.Show(GetType(Form3))
        End Sub
    End Class



    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2018年1月3日 下午 01:49
    版主
  • VB2005 起,恢復 VB6 特性,預設內建同名 Form ,亦即,你執行檔一跑,就有個物件名為 Form2 型別名為 Form2 的存在。

    你如果重複使用 Form2 ,你可以 Show / Hide

    你如果重複載入 Form2 ,就要搭配 Dim / Dispose


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2018年1月3日 下午 03:54
  • TO:Bill Chung

    非常謝謝您分享您的程式碼

    我最初的目的就是要讓form2重新啟動 讓資料重讀  這的確有達到我想要的效果

    因為有時候會按到form1 雖然再去點開form2就好 不過我懶:)

    TO:心冷熱情熄

    謝謝您的知識

    我會在研究看看它們的搭配

    2018年1月3日 下午 04:16
  • TO:Bill Chung

    您的 Form 顯示管理器 非常好用,節省了我很多的時間

    但我碰到了一些問題,雖然我努力嘗試避開問題,修改問題,但仍然還是沒辦法

    我努力研究一段時間,但有覺得奇怪的地方

    當我使用

    FormsManager.Instance.Show(GetType(Form3))

    開啟程式碼時我想要form2關閉時連同form3一起關閉

    但沒有辦法

    例如:

        

    'form2

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click fomr3.Close() fomr3.Dispose() Me.Close() End Sub


    我試著瞭解您給的程式碼,目前知道當我在form2使用Button1 的時候會進到程式碼裡

    會進到 1,4,3

    Class FormsManager2
    
            Private _forms As Dictionary(Of Type, Form)
    
            Private Sub New()
                _forms = New Dictionary(Of Type, Form)
                MsgBox("1")
            End Sub
    
            Public Sub Dispose(type As Type)
                If _forms.ContainsKey(type) Then
                    _forms(type).Dispose()
                    _forms.Remove(type)
                    MsgBox("2")
                End If
                _forms(type) = DirectCast(Activator.CreateInstance(type), Form)
                _forms(type).Dispose()
                MsgBox("3")
            End Sub
    
    
            Private Shared _instance As FormsManager2
            Public Shared ReadOnly Property Instance As FormsManager2
                Get
                    If _instance Is Nothing Then
                        _instance = New FormsManager2()
                        MsgBox("4")
                    End If
                    Return _instance
                    MsgBox("5")
                End Get
            End Property
    
        End Class

    如我我重複點開form3沒有

    總額言之 我卡在 form2關閉時form3關不掉

    希望大大能幫我解答!

    2018年5月22日 上午 09:17
  • 如果你要使用 FormsManager , 此時 FormsManager 就是一個管理者, 除了 Form 本身關閉自己的行為外,所有外部的操作 (比方你說從 form2 去關 form3 ) 都應該透過 FormsManager 來處理。

    也就是說, 你應該為 FormsManager 增加 Close 的行為, form2 是呼叫 FormsManager 去關閉 form3


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2018年5月22日 上午 09:32
    版主
  • 我嘗試修改原本的程式碼把有關Show()的地方改成Close,或者是在其他地方增加XXX.Close()幾乎都是錯的

    嘗試重新組裝修改,也是組不起來,google"FormsManager"似乎也沒文章

    不知道有沒有相關文章或者是例子?

    2018年5月22日 下午 01:36
  • 我想主要是

     Public Sub Show(type As Type)
                If _forms.ContainsKey(type) Then
                    _forms(type).Close()
                    _forms.Remove(type)
                    MsgBox("123")
                End If
                _forms(type) = DirectCast(Activator.CreateInstance(type), Form)
                _forms(type).Close()
                MsgBox("321")
            End Sub

    這段 但我還在事

    2018年5月22日 下午 01:48
  • 哦哦~  我大概懂了!

    我以為 要直接增加FormsManager2 來控制我的Close()

    原來動作要在同一個FormsManager才能執行

    2018年5月22日 下午 01:57
  • 這個設計就是把 FormsManager 當作一個中控台使用, 既然所有使用的 forms 都註冊在此,當然都要存取同一個註冊表啊。
    註: 你查 FormsManager 找不到甚麼參考文章是正常的,因為那是我看了你的需求想出來的東西。

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/


    2018年5月22日 下午 03:22
    版主