如何安全的使用多线程???

Diboy 2003-04-09 11:18:44
在 vb6 中如何安全的使用多线程序
我找一个多线程序的例子,但实在是太不稳定了,跑着跑着就挂了
不知哪位我比较好的办法,附上我的代码
clsThreads.cls
------------------
Option Explicit
Private Declare Function CreateThread Lib "kernel32" (ByVal pThreadAttributes As Any, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, lpParameter As Any, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
Private Declare Function ResumeThread Lib "kernel32" (ByVal hThread As Long) As Long
Private Declare Function SuspendThread Lib "kernel32" (ByVal hThread As Long) As Long

Public ThreadStatus As Boolean
Private Thread As Long
Public Property Let Enabled(ByVal vNewValue As Boolean)
If vNewValue = True And Me.ThreadStatus = False Then
ResumeThread Thread
Me.ThreadStatus = True
ElseIf Me.ThreadStatus = True Then
SuspendThread Thread
Me.ThreadStatus = False
End If
End Property

Public Sub Initialize(lpfnBasFunc As Long)
Dim dwStackSize As Long
Dim dwCreationFlags As Long
Dim lpThreadId As Long
Dim lpParameter As Long
Dim myNull As Long
myNull = 0& 'create a null pointer
dwStackSize = 0 '0±íʾÓÃexe stack size
dwCreationFlags = 4 'ÓÃ4±íʾ³õʼ»¯ºóÏȲ»¼¤»î,ÈñðÈËÀ´¼¤»î.
Thread = CreateThread(myNull, dwStackSize, lpfnBasFunc, myNull, dwCreationFlags, lpThreadId)
If Thread = myNull Then
MsgBox "create thread failed"
End If
End Sub
---------
module

Option Explicit

Public Sub Test1()
Dim i As Long
For i = 0 To 9999
Debug.Print ("SSSSSSSSSSSSS")
Next
End Sub
Public Sub Test2()
Dim i As Long
For i = 0 To 9999
Debug.Print ("*************")
Next
End Sub

---
form
---
Dim myThread1 As New ClsThreads
Dim myThread2 As New ClsThreads

Private Sub Command1_Click()
'make new thread object
'Dim myThread As New ClsThreads
'´´½¨ÏØ³Ç Foo
myThread1.Initialize AddressOf Test1
'¼¤»îÏسÇ
myThread1.Enabled = True

End Sub

Private Sub Command2_Click()
'´´½¨ÏØ³Ç Foo
myThread2.Initialize AddressOf Test2
'¼¤»îÏسÇ
myThread2.Enabled = True
End Sub

Private Sub Command3_Click()
myThread1.Enabled = False
End Sub
Private Sub Command4_Click()
myThread2.Enabled = False
End Sub
...全文
42 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
fbmsf 2003-04-14
  • 打赏
  • 举报
回复
就是 启动多个进程,只是在参数的传递上,比较麻烦
maskzha 2003-04-14
  • 打赏
  • 举报
回复
用多进程是不是好一点?
suntt 2003-04-14
  • 打赏
  • 举报
回复
呵呵,vb中的多线程本来是不稳定的,可以考虑vb.net
叶帆 2003-04-14
  • 打赏
  • 举报
回复
你可以用控件,DLL代替
Diboy 2003-04-14
  • 打赏
  • 举报
回复
fbmsf(FBM) 你的多进程怎么写??启动多个程序吗??
fbmsf 2003-04-13
  • 打赏
  • 举报
回复
因为我写不出来,我因此用多进程。
多线程的列子也有但都不实用,都不太稳定,这个算vb6先天不足
用户 昵称 2003-04-10
  • 打赏
  • 举报
回复
vb6多线程就是不稳定。封装起来也同样。比较好的方法是写安全的线程函数,一旦线程出错,不会对主程序做出大的影响,而主程序可以用timer定期检查线程。
Diboy 2003-04-10
  • 打赏
  • 举报
回复
JennyVenus() 怎么写出写安全的线程函数
fbmsf 2003-04-09
  • 打赏
  • 举报
回复
vb6用多线程没戏,都不稳定
Diboy 2003-04-09
  • 打赏
  • 举报
回复
The solution lies again in the nature of apartment-model threading. Every time a thread is created, the application's Sub Main function is called; this means that you can look at the App.StartMode property and determine whether the thread was started externally. You can then set a global flag (which, of course, is specific to that thread, so it won't interfere with other objects) so that the object will know during its Initialize event whether or not it should enable itself. An example of this is shown in the following code from the code module:

Public BlockLoad As Boolean
Public Sub Main()
If App.StartMode <> vbSModeStandalone Then
BlockLoad = True
Exit Sub
End If
¡­. Do other initialization here
End If

And this code in the class module:

Private Sub Class_Initialize()
If BlockLoad Then
Err.Raise vbObjectError + 1000, "clsBackground",_
"Can't initialize object"
Else
f.Show
End If
End Sub

You'll need to do this with every public class that you don't want other applications to access.

How can I tell whether Sub Main is being called due to an initial program execution or the start of a new thread?

The first time Sub Main is called, it will be due to the initial launch of a program. But Sub Main will be called again for each new thread. At first glance, you might think to use a global variable to flag whether this is the first call or not, but remember-global variables are thread-specific when using apartment-model threading. One possible approach is shown in the following code:

Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" (ByVal lpClassName As String,_
ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId _
Lib "user32" (ByVal hwnd As Long, lpdwProcessId As _
Long) As Long
Private Declare Function GetCurrentProcessId Lib _
"kernel32" () As Long
Public BlockLoad As Boolean
Public Sub Main()
Dim pid As Long
Dim OtherWnd As Long
If App.StartMode <> vbSModeStandalone Then
BlockLoad = True
Exit Sub
End If
If App.PrevInstance = True Then
MsgBox "Can only run one instance of this app"
Exit Sub
End If
' Is the main window already up?
OtherWnd = FindWindow(vbNullString, "Foreground _
Form")
If OtherWnd <> 0 Then
' Make sure it's the same process - don't want
' to interfere with others
Call GetWindowThreadProcessId(OtherWnd, pid)
If pid = GetCurrentProcessId() Then
' Main window is up in the same process,
' so exit
Exit Sub
End If
End If
frmMain.Show ' Show the main window
End Sub

The server loads the main application form the first time it's called. During subsequent calls, the Sub Main function checks to see whether the main form exists by looking for a window with the correct caption that belongs to the same process. Actually, this code is flawed in that it only checks the first window with the specified caption. If you have another application that uses the same window caption, this code might fail. A better solution would be to enumerate all of the top-level windows looking for one with the correct characteristics. Enumeration techniques can be found in Chapter 5 of my Visual Basic 5.0 Programmer's Guide to the Win32 API. If you used the enumeration approach, you could also change the application to allow more than one instance to run at a time. The single instance limitation is placed here because you can't predict which server will implement a particular object if you have more than one server running.

The preceding code combines the techniques described earlier to demonstrate a fairly complete Sub Main implementation. The missing piece of the puzzle is the background class, whose implementation code is shown here:

Dim f As New frmBackground
Private Sub Class_Initialize()
If BlockLoad Then
Err.Raise vbObjectError + 1000, "clsBackground",_
"Can't initialize object"
Else
f.Show
End If
End Sub

tools for developers. dan@desaware.com, 70303.2252@compuserve.com.
Diboy 2003-04-09
  • 打赏
  • 举报
回复
What a difference a few dialog controls make

In the original VB5, the multi-threading capabilities of an ActiveX server were set in the Project Properties (General) dialog box. This dialog box included a check box titled "Unattended Execution" and two option buttons: one marked "Thread per object," the other "Thread Pool," with the number of threads specified in a text box.

The "Unattended Execution" check box first prevented the server from using any user interface elements such as forms or message boxes. This was the first requirement for multi-threading with VB, because the VB forms engine was not thread-safe. VB uses the so-called "apartment model" of multi-threading, in which all of your components' global variables are thread-specific. In other words, VB makes a separate copy of all of your global variables for each thread. This eliminates most shared memory and synchronization problems, making apartment-model multi-threading relatively safe and easy to use. But because VB5 could not isolate form level variables among threads, it required that multi-threading servers have no user interface elements.

With VB5 SP2, Microsoft figured out how to isolate forms between threads, extending the forms engine to run in the apartment model as well. The "Unattended Execution" check box is still there, but now it's completely independent of the server's multi-threading capabilities.

The multi-threading options are selected in two ways:

ActiveX DLL servers and controls use the "Threading Model" combo box to select between two available threading models-Apartment Model or Single-Threaded.


ActiveX EXE servers use the "Thread per object" or "Thread Pool" option buttons as before. A non-multi-threading EXE server is one that uses a thread pool with a single thread.
In other words, setting Unattended Execution has nothing to do with multi-threading.

The impact of this change on DLL servers is both profound and trivial at the same time. Profound, in that ActiveX DLL servers can now include forms and, more importantly, that ActiveX controls can be marked for apartment-model multi-threading-allowing them to run more efficiently on multi-threading clients such as Internet Explorer. Trivial, in that this requires virtually no effort on the part of the programmer besides changing a combo box option and testing the server using a multi-threading client.

The impact of this change on EXE servers is really limited to one small but crucial area. For most servers there will be no change at all-adding forms to EXE servers that are accessed from other applications is generally pointless. But this change does allow you to create true multi-threading clients using VB. For the rest of this article, we'll explore some of the subtleties involved in doing this.

Multi-threading clients Q&A

Implementing multi-threaded clients using VB5 SP2 raises a number of interesting questions. Rather than simply showing you the answers and resulting code, I've decided to illustrate the techniques involved by using a question-and-answer format, where the questions are ones that I asked myself when first starting out. Keep in mind that we're talking about some very new capabilities in VB, so I haven't had much time to work with them. I won't promise that these are the best possible answers-only that they work. I'll try to suggest other possible solutions along the way as well.

Which threading model should I use?

This is an easy one. A multi-threading client application must be created as an ActiveX EXE server. It's the only model that supports the creation of objects on their own threads. Set the threading option to "Thread per object."

How can I make an ActiveX EXE server behave like a standalone application?

Nothing has changed from the original VB5. You'll need to create a module that contains a Sub Main and set Sub Main as the startup object. Then you'll look at the App.StartMode property-if it's vbSModeStandalone, the server was started as a standalone program and you can show the main form. Once the main form is shown, the server will not terminate until the form is closed and terminated.

If App.StartMode = vbSModeStandalone Then
frmMain.Show
End If

Wait-I have some objects that I don't want to be created in their own threads!

Your application will probably have many objects, only one or two of which you'd want to run in their own thread. Fortunately, VB makes it easy to control which thread an object is created in. Say you have an object called "clsBackground" in a server called ThreadTest1. The following code will create the object in a new thread:

Dim s As clsBackground
Set s = CreateObject("ThreadTest1.clsBackground")

The following code will create the object in the current thread:

Dim s As clsBackground
Set s = New clsBackground

You must use the CreateObject function to create an object in its own thread.

How can I prevent other applications from accessing my public objects?

One of the side effects of this approach to multi-threading is that your application must publicly expose the objects that you wish to run in their own threads. But you probably won't want other applications to access those objects. Disabling an object is easy-you can raise an error during its Initialize event and otherwise disable its operation. Make the termination as ugly as you'd like-nobody is supposed to access that object externally in the first place.

The trick is knowing when the object has been created within your own application.

Diboy 2003-04-09
  • 打赏
  • 举报
回复
这有篇资料,哪们仁兄看一看

Creating Multi-Threaded VB5/SP2 Apps
Daniel Appleman

Have you noticed that Dan has avoided discussing multi-threading in VB5? The reason is simple: He didn't think it was particularly safe to create multi-threaded applications with the original version of VB5. But now that Service Pack 2 is available, it's a different story.

Several people have recently asked me how to create multiple threads in VB5 applications. Some have mentioned the CreateThread API and wondered why I didn't discuss it in my Win32 API book. Well, I'll have a few things to say about the CreateThread API later. You see, I believe it's my responsibility to address not only what you can do with VB, but what you should do as well-and the CreateThread API opens a nest of problems that programmers should face with trepidation, if not outright terror. For the past couple of months I've been answering VB threading inquiries with a cryptic "just wait." I was using the beta version of the new VB Service Pack 2 (SP2), so I knew what was coming. This update to VB5 allows you to create multi-threaded VB5 applications safely.

Now, if you aren't familiar with multi-threading, this column isn't going to make much sense to you. One good source of information is Chapter 14 of my book Developing ActiveX Components with Visual Basic 5.0: A Guide to the Perplexed. This article assumes that you're familiar with multi-threading as it was implemented in VB5.



1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧