委托,开始调用。 EndInvoke - 如何清除对同一委托的多个异步威胁调用?

发布于 2024-08-20 15:02:08 字数 985 浏览 12 评论 0原文

我创建了一个委托,我打算将其称为异步。

模块级别

Delegate Sub GetPartListDataFromServer(ByVal dvOriginal As DataView, ByVal ProgramID As Integer)
Dim dlgGetPartList As GetPartListDataFromServer 

我在方法中使用以下代码

    Dim dlgGetPartList As New GetPartListDataFromServer(AddressOf AsyncThreadMethod_GetPartListDataFromServer)
    dlgGetPartList.BeginInvoke(ucboPart.DataSource, ucboProgram.Value, AddressOf AsyncCallback_GetPartListDataFromServer, Nothing) 

该方法运行并执行所需的操作

在完成 EndInvoke 时会触发 Asyn 回调

Sub AsyncCallback_GetPartListDataFromServer(ByVal ar As IAsyncResult)
    dlgGetPartList.EndInvoke(Nothing)
End Sub

只要在委托上启动 BeginInvoke 的方法仅在存在时运行,它就可以工作不是正在运行的 BeginInvoke/Thread 操作。问题是,当委托上的另一个线程仍在运行且尚未被 EndInvoke 时,可能会调用新线程。

如有必要,程序需要能够让委托一次在多个实例中运行,并且它们都需要完成并调用 EndInvoke。一旦我启动另一个 BeginInvoke,我就会丢失对第一个 BeginInvoke 的引用,因此我无法使用 EndInvoke 清理新线程。

克服这个问题的干净解决方案和最佳实践是什么?

I've created a Delegate that I intend to call Async.

Module Level

Delegate Sub GetPartListDataFromServer(ByVal dvOriginal As DataView, ByVal ProgramID As Integer)
Dim dlgGetPartList As GetPartListDataFromServer 

The following code I use in a method

    Dim dlgGetPartList As New GetPartListDataFromServer(AddressOf AsyncThreadMethod_GetPartListDataFromServer)
    dlgGetPartList.BeginInvoke(ucboPart.DataSource, ucboProgram.Value, AddressOf AsyncCallback_GetPartListDataFromServer, Nothing) 

The method runs and does what it needs to

The Asyn callback is fired upon completion where I do an EndInvoke

Sub AsyncCallback_GetPartListDataFromServer(ByVal ar As IAsyncResult)
    dlgGetPartList.EndInvoke(Nothing)
End Sub

It works as long as the method that starts the BeginInvoke on the delegate only ever runs while there is not a BeginInvoke/Thread operation already running. Problem is that the a new thread could be invoked while another thread on the delegate is still running and hasnt yet been EndInvoke'd.

The program needs to be able to have the delegate run in more than one instance at a time if necessary and they all need to complete and have EndInvoke called. Once I start another BeginInvoke I lose the reference to the first BeginInvoke so I am unable to clean up the new thread with an EndInvoke.

What is a clean solution and best practice to overcome this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

丢了幸福的猪 2024-08-27 15:02:08

您只需要保留对委托的一个引用;您不需要每次调用时都创建一个新的。

不要将 Nothing 传递给 EndInvoke,而是传递 ar。这将为您提供该特定调用的结果。

Sub AsyncCallback_GetPartListDataFromServer(ByVal ar As IAsyncResult)
    dlgGetPartList.EndInvoke(ar)
End Sub

如果您希望能够取消特定的调用,那么您需要保留 BeginInvoke 的结果(它与传递的 IAsyncResult 的实例相同)在上面的回调中给你)。

You only need to hold on to one reference to the delegate; you don't need to create a new one every time you invoke.

Rather than passing Nothing to EndInvoke, pass ar. This will give you the result of that specific invocation.

Sub AsyncCallback_GetPartListDataFromServer(ByVal ar As IAsyncResult)
    dlgGetPartList.EndInvoke(ar)
End Sub

If you want to be able to cancel a specific invocation, then you'll want to hold on to the result of BeginInvoke (which is the same instance of IAsyncResult that gets passed to you in your callback above).

关于从前 2024-08-27 15:02:08

调用 BeginInvoke 时,需要将该对象作为状态参数传递。

    class Program

    {
        delegate void SampleDelegate(string message);

        static void SampleDelegateMethod(string message)
        {
            Console.WriteLine(message);
        }
        static void Callback(object obj)
        {
            IAsyncResult result = obj as IAsyncResult;

            SampleDelegate del = result.AsyncState as SampleDelegate; 
            del.EndInvoke(result);
            Console.WriteLine("Finished calling EndInvoke");
        }
        static void Main()
        {
            for (int i = 0; i < 10; i++)
            {
                // Instantiate delegate with named method:
                SampleDelegate d1 = SampleDelegateMethod;
               //d1 is passed as a state
                d1.BeginInvoke("Hello", Callback, d1);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadLine();
        }
    }

You need to pass the object as a state argument when you call BeginInvoke.

    class Program

    {
        delegate void SampleDelegate(string message);

        static void SampleDelegateMethod(string message)
        {
            Console.WriteLine(message);
        }
        static void Callback(object obj)
        {
            IAsyncResult result = obj as IAsyncResult;

            SampleDelegate del = result.AsyncState as SampleDelegate; 
            del.EndInvoke(result);
            Console.WriteLine("Finished calling EndInvoke");
        }
        static void Main()
        {
            for (int i = 0; i < 10; i++)
            {
                // Instantiate delegate with named method:
                SampleDelegate d1 = SampleDelegateMethod;
               //d1 is passed as a state
                d1.BeginInvoke("Hello", Callback, d1);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadLine();
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文