Не удается заставить хранимую процедуру запускаться параллельно с задачей регистрации в C# Winform - PullRequest
1 голос
/ 04 августа 2020

Я новичок ie с C#. Я пытаюсь запустить задачу параллельно с выполнением хранимой процедуры. Так, например, у меня есть хранимая процедура, которая в этом случае будет просто запускать WAITFOR DELAY '00: 00: 10 '. В течение этих десяти секунд метка будет заполнена текстом, к которому будут добавлены точки, а затем будут удалены, как вы увидите на экране загрузки.

Отключение репликации. Отключение репликации ... Отключение репликации ...

Как только pro c будет завершен, он выйдет из игры while l oop. Это обрабатывается логическим значением. Итак, _IsRunning = false, запустите хранимую процедуру, а затем установите IsRunning = true. Код работает точно так, как я бы хотел, если бы я просто использовал Thread.Sleep (1000), который я использовал для целей тестирования, вместо хранимой процедуры.

Может кто-нибудь сказать мне, почему это не сработает, когда используя хранимую процедуру? Он просто застревает на while l oop и постоянно говорит Отключение репликации с полной остановкой загрузки.

using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsynchronousCoding
{
    public partial class Form1 : Form
    {
        private DataAccess _access = new DataAccess();


        public Form1()
        {
            InitializeComponent();
        }
        


        private async Task LoadRapport()
        {

            await DisableReplication();


        }


        private async Task DisableReplication()
        {
            Task.Factory.StartNew(TestMethod);
            await Task.Factory.StartNew(() => ShowProgressText("Disabling Replication"));
        }

        private bool _IsRunning;

        private void TestMethod()
        {
            _isRunning= false;
            //Thread.Sleep(10000);
            _access.Rapport_ReplicationSetting();
            _isRunning= true;
        }


        private void ShowProgressText(string txt)
        {
            var count = 0;
            var logText = new StringBuilder();

            logText.Append(txt);
            var baseLen = logText.Length;

            while (!_isRunning)
            {
                Thread.Sleep(250);
                if (count >= 3)
                {
                    logText.Remove(baseLen, count);
                    count = 0;
                }

                logText.Append(".");
                count++;

                BeginInvoke(new Action(() => { UpdateProgressText(logText.ToString()); }));

            }

            BeginInvoke(new Action(() => { UpdateProgressText(txt + " - Complete"); }));
            Thread.Sleep(2000);
        }
        private void UpdateProgressText(string txt)
        {
            lblProgress.Text = txt;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            LoadRapport();
        }
    }
}

1 Ответ

1 голос
/ 04 августа 2020

Рассмотрим этот простой пример с использованием CancellationToken. Я не предлагаю bool, это не потокобезопасно.

private async void button1_Click(object sender, EventArgs e)
{
    IProgress<string> progress = new Progress<string>(s => lblProgress.Text = s);
    using (CancellationTokenSource cts = new CancellationTokenSource());
    {
        Task animationTask = ProgressAnimationAsync(progress, cts.Token);
        await DoSomeJobAsync();
        // await Task.Run(() => DoSomeHeavyJob()); // uncomment for test
        cts.Cancel();
        await animationTask;
    }
}

private async Task ProgressAnimationAsync(IProgress progress, CancellationToken token)
{
    int i = 1;
    while (!token.IsCancellationRequested)
    {
        progress.Report("Loading" + new string("." , i));
        i = i == 3 ? 1 : i + 1;
        await Task.Delay(250);
    }
}

// as I/O-bound operation
private async Task DoSomeJobAsync()
{
    await Task.Delay(10000);
}

// as CPU-bound operation
private void DoSomeHeavyJob()
{
    Thread.Sleep(10000);
}

Есть два разных метода, вы можете протестировать оба.

Примечание: использовать lblProgress.Text напрямую здесь без IProgress синхронизированного обратного вызова. Это дано здесь только для примера. Создайте new Progress в потоке пользовательского интерфейса, и вы можете безопасно вызывать .Report() из любого другого потока без Invoke или BeginInvoke.

Подробнее об операциях с привязкой к X можно узнать здесь .

...