将参数传递给线程化的LongRunningProcess [英] Passing arguments to a threaded LongRunningProcess
问题描述
johnsontroye'关于UI响应的文章让我大部分时间都遇到了在单独的线程上运行long方法的问题,但是我的应用程序有几个输入和返回的数据不适合这个例子。
似乎输入数据是正确的,但 API
调用无法正常运行。
我使用的是标准的Windows窗体而不是WPF,我将示例应用到我的应用程序并使用模拟的LongRunningMethod运行,但我无法将参数传递正确(?)我的LongRunningMethod(API调用):
johnsontroye''s article on UI Responsiveness got me most of the way through the problem of running a long method on a separate thread, but my application has several inputs and returned data that does not fit the example.
It seems as though the input data is correct, but the API
call does not run correctly.
I am using a standard windows form instead of WPF, and I adapted the example to my application and got it running with the simulated LongRunningMethod, but I cannot get the argument passing correct (?) for my LongRunningMethod (API Call):
Private Function SomeLongRunningMethod((ByRef abData1() As Byte, _
ByRef abData2() As Byte, _
ByVal n As Integer, _
ByRef abData3() As Byte) As String
Dim someString as string = "1"
abData1 = Method(abData1, abData2, n, abData3) ''API call
Return SomeString
End Function
abData1()
是一个大字节数组,与Method返回相同。
我很感激我能得到的任何帮助,因为我在很多例子中苦苦挣扎。
[已编辑]代码在预标签中被阻止[ / edited]
abData1()
is a large byte array, and is the same as the Method return.
I would appreciate any help I can get with this, as I have struggled through many examples.
Code is blocked in "pre" tags[/Edited]
推荐答案
由于某种原因,建议的方法是使用System.Threading.ParameterizedThreadStart
。
我从来没有这样做过!您必须传递System.Object
参数,因此运行时间将是所有参数的某个容器(struct
,例如);并且在线程代码中你需要将System.Object
强制转换回你的结构,这是不安全的。
我从来不明白为什么要这么丑陋的事情。有一个更好的方法。您只需传递我参考。我将整个线程包装在某个类中并创建一个方法,线程应该在我调用Body
时启动。我做了它和实例(非静态)方法,没有参数(重要!)。使用常规构造函数System.Threading.Thread(ThreadStart)
允许传递Body
。
由于Body
是一个实例方法,所以包装类的所有成员都通过不可见参数Me
包装类的类型;并且此参数无形地传递给Body
。没有什么不寻常的 - 这就是所有实例方法的工作方式。但结果是,包装器Body
的方法在一个线程中启动,并且该方法的成员类实例的所有成员都可见。因此,首先实例化包装类。您的问题中提到的所有参数都应该是包装器的成员。您需要在Thread.Start
之前初始化它们。例如,你可以在包装器的构造函数中传递所有这些值。
我有一个完整的代码示例,但它在C#中:
如何将ref参数传递给线程 [ ^ ]。
尽管如此,使用我的解释很容易理解它是如何工作的。
祝你好运,
-SA
By some reason, the suggested method is usingSystem.Threading.ParameterizedThreadStart
.
I never do this! You have to pass aSystem.Object
argument, so run-time time would be of some container for all your parameters (struct
, for example); and in the thread code you need to castSystem.Object
back to your structure, which is unsafe.
I never understood why doing such ugly things. There is a much better way. All you need is to pass "Me" reference. I wrap whole thread in some class and create a method the thread should be started with I callBody
. I make it and instance (non-static) method, without parameters (important!). Using a regular constructorSystem.Threading.Thread(ThreadStart)
allows to passBody
.
AsBody
is an instance method, all members of the wrapper class are passed through the invisible parameter "Me
" of the type of the wrapper class; and this parameter is passed invisibly toBody
. There is nothing unusual about it — this is how all instance methods work. But as a result, the method of the wrapperBody
is started in a thread and all members of the instance of the member class are visible inside the method. So, you instantiate the wrapper class first. All parameters mentioned in your Question should be members of the wrapper. You need to initialize them beforeThread.Start
. For example, you can pass all those values in the wrapper''s constructor.
I have a complete code sample, but it is in C#:
How to pass ref parameter to the thread[^].
Nevertheless it''s quite easy to understand how it work using my explanation.
Good luck,
—SA
我实施了SAKryukov建议的解决方案简化了变量的传递,API调用立即终止。我通过获取三个字节数组的散列并返回结果以与发送的变量进行比较来测试传递给线程的变量。此测试验证数据是否正确传递给线程,并且可以返回该数据。 API方法在主线程上正确运行。
I implemented the solution suggested by SAKryukov and while it simplifies the passing of variables, the API call terminates instantly. I did a test of the variables passed to the thread by taking a hash of the three byte arrays and returning the results for comparison with the variables sent. This test verifies that data is correctly passed to the thread and that data can be returned. The API method runs correctly on the main thread.
Imports VB = Microsoft.VisualBasic
Imports CryptoSysAPI
Imports System.IO
Imports System
Imports System.Threading
Public Class ThreadWrapper
Public Sub New(ByRef abData() As Byte, _
ByRef abKey() As Byte, _
ByVal n As Integer, _
ByRef abInitV() As Byte)
Initialize data passed to ThreadWrapper.
ReDim abData1(0)
ReDim abData2(0)
ReDim abData3(0)
abData1 = abData
abData2 = abKey
n1 = n
abData3 = abInitV
thread = New System.Threading.Thread(AddressOf Body)
End Sub
Public Sub start()
Me.thread.Start()
End Sub
Public Sub join()
Me.thread.Join()
End Sub
Public Sub Body()
'' The API call.
Me.abData1 = Blowfish.Encrypt(Me.abData1, Me.abData2, n1, Me.abData3)
End Sub
'' The definitions of the data passed to ThreadWrapper Class.
Private abData1() As Byte
Private abData2() As Byte
Private n1 As Integer
Private abData3() As Byte
Public thread As System.Threading.Thread
End Class
'' This is the call to the ThreadWrapper class to create a new thread and start the thread.
'' All inputs are byte array except Mode.CBC which is an integer.
Public Class Protect
Public Function Encyrpter(Inputs....) as Integer
Dim tw As New ThreadWrapper(X_abData1, _
X_abDerivedKeyHex, _
Mode.CBC, _
abInitVector, _
X_abData3)
tw.start()
tw.join()
End Function '' Encrypter.
End Class '' Protect.
VSNetVbHarry
VSNetVbHarry
这篇关于将参数传递给线程化的LongRunningProcess的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!