79273775

Date: 2024-12-12 03:53:10
Score: 1
Natty:
Report link

As I explained in comment above I had wrong interface search in registry for NewAsyncCallbackTest.INewCallback instead of INewCallback and I have also used NewAsyncCallbackTest.INewCallback in VBA so I thought I miss INewCallback.

So as @Hans Passant said: nothing wrong with C# Code: NewAsyncTaskRunner.cs. Used attribute InterfaceIsIDispatch. DLL is properly registered.

So the correct approach in VBA:

class module TaskRunnerEventHandler

Option Compare Database
Option Explicit

Implements INewCallback 

Private Sub INewCallback_OnTaskCompleted(ByVal result As String)
    Debug.Print result
End Sub

Usage module

Option Compare Database
Option Explicit

Dim obj As Object
Dim CallbackHandler As CallbackHandler

Sub StartTask(taskParam As String)
    Set CallbackHandler = New CallbackHandler
    Set obj = CreateObject("NewAsyncCallbackTest.NewAsyncTaskRunner")
    obj.RunAsyncTask taskParam, CallbackHandler
End Sub

Sub TestMultipleTasks()
    Dim i As Integer
    
    ' Loop ten times to check multiple tasks
    For i = 1 To 10
        StartTask "Task " & i
        Sleep 100
        Debug.Print "Task " & i & " is running asynchronously!"
    Next i
End Sub

But I'm also curious to use [ComSourceInterfaces] attribute as @Hans Passant mentioned as standard approach in VBA but I'm doing some wrong...

ITaskRunnerEvents.cs

using System;
using System.Runtime.InteropServices;

namespace ComEventTest
{
    [ComVisible(true)]
    [Guid("c8614250-4291-4fb0-8b45-4aa305b0c595")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface ITaskRunnerEvents
    {
        void OnTaskCompleted(string result);
    }
}

TaskRunner.cs

using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace ComEventTest
{
    [ComVisible(true)]
    [Guid("ac9de195-73e8-44ae-8cf1-d8f110421923")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(ITaskRunnerEvents))]
    public class TaskRunner
    {
        // Declare the delegate for the event
        public delegate void TaskCompletedEventHandler(string result);

        // Declare the event
        public event TaskCompletedEventHandler OnTaskCompleted;

        // Method to start the async task
        public void RunTask(string input)
        {
            Task.Run(async () =>
            {
                await Task.Delay(5000); // Simulate work
                OnTaskCompleted?.Invoke($"Task completed with input: {input}");
            });
        }
    }
}

VBA Side:

ClassModule TaskRunnerEventHandler

Option Compare Database
Option Explicit

Public WithEvents taskRunner As ComEventTest.taskRunner

Private Sub taskRunner_OnTaskCompleted(ByVal result As String)
    MsgBox result
End Sub

Public Sub InitializeTaskRunner()
    Set taskRunner = New ComEventTest.taskRunner
End Sub

Usage module

Sub TestTaskRunner()
    Set eventHandler = New TaskRunnerEventHandler
    eventHandler.InitializeTaskRunner
    eventHandler.taskRunner.RunTask "Test Input"
End Sub

I have a problem here: eventHandler.taskRunner.RunTask "Test Input" err: Method or data member not found

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Hans
  • User mentioned (0): @Hans
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Adrijano Toys Shop