Один более длинный вызов вызывает приостановку или блокировку всех параллельных циклов - PullRequest
0 голосов
/ 10 декабря 2018

Я вызываю dll VB 6.0 в Parallel.ForEach и ожидаю, что все вызовы будут запущены одновременно или как минимум 2 из них в зависимости от доступности ядер или потоков моего компьютера в пуле потоков

VB6 dll

Public Function DoJunk(ByVal counter As Long, ByVal data As String) As Integer
    Dim i As Long
    Dim j As Long
    Dim s As String

    Dim fno As Integer
    fno = FreeFile
    Open "E:\JunkVB6Dll\" & data & ".txt" For Output Access Write As #fno
    Print #fno, "Starting loop with counter = " & counter
    For i = 0 To counter
        Print #fno, "counting " & i
    Next

    Close #fno
    DoJunk = 1
End Function

счетчик передается от вызывающей стороны для управления временем выполнения вызова, а файл записывается для того, чтобы сделать его процессом на основе ввода-вывода.

C # вызывающая сторона

private void ReportProgress(int value)
{
    progressBar.Value = value;
    //progressBar.Value++;
}

private void button1_Click(object sender, EventArgs e)
{
    progressBar.Value = 0;
    counter = 0;
    Stopwatch watch = new Stopwatch();
    watch.Start();

    //var range = Enumerable.Range(0, 100);
    var range = Enumerable.Range(0, 20);

    bool finished = false;


    Task.Factory.StartNew(() =>
    {
        Parallel.ForEach(range, i =>
        {
            #region COM CALL
            JunkProject.JunkClass junk = new JunkProject.JunkClass();
            try
            {
                Random rnd = new Random();
                int dice = rnd.Next(10, 40);

                int val = 0;
                if (i == 2)
                    val = junk.DoJunk(9000000, i.ToString());
                else
                    val = junk.DoJunk(dice * 10000, i.ToString());
                System.Diagnostics.Debug.Print(junk.GetHashCode().ToString());

                if (val == 1)
                {
                    Interlocked.Increment(ref counter);
                    progressBar.Invoke((Action)delegate { ReportProgress(counter); });
                }
                junk = null;
            }
            catch (Exception excep)
            {
                i = i;
            }
            finally { junk = null; }
            #endregion
        });
    }).ContinueWith(t =>
    {
        watch.Stop();
        MessageBox.Show(watch.ElapsedMilliseconds.ToString());
    });
}

Эта строка делает определенный вызов длиннее других.

val = junk.DoJunk(9000000, i.ToString());

Здесь этот второй процесс вызывает остановку всех вызовов внутри Parallel.ForEach, т. Е. Никакой другой файл не создается, если этот второй вызов не будет завершен.

Это ожидаемое поведение или я делаю что-то не так?

1 Ответ

0 голосов
/ 11 декабря 2018

Поскольку @John Wu предложил создать AppDomain для запуска COM в другом домене приложений, я полагаю, вы можете запустить свою параллель следующим образом.

        Parallel.ForEach(range, i =>
        {
            AppDomain otherDomain = AppDomain.CreateDomain(i.ToString());
            otherDomain.DoCallBack(delegate
            {
                //Your COM call
            });
        });

EDIT

Верно .. Я не уверен, как вы можете установить сериализуемость в классе VB6.0.Вы можете попробовать другой способ (маршалинг объектов по ссылке).Отметил: я на самом деле не проверял это, но я хотел бы знать, будет ли это работать.

        Parallel.ForEach(range, i =>
        {
            AppDomain otherDomain = AppDomain.CreateDomain(i.ToString());
            var comCall = (ComCall) otherDomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, typeof(ComCall).ToString());
            comCall.Run();
            AppDomain.Unload(otherDomain);
        });

и класс

public class ComCall : MarshalByRefObject
{
    public void Run()
    {
        //Your COM Call
    }
}

Вот также дополнительная ссылка по теме.

https://www.codeproject.com/Articles/14791/NET-Remoting-with-an-easy-example

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...