1

ビデオがバックグラウンドで処理されるときにユーザーに完了ステータスを表示するプログレスバーを実装しました。単一のインスタンスでうまく機能します。しかし、2つの同時ビデオプロセスが開始されたときにそれを混同しました。

2人の異なるユーザーによって同時に開始された2つのビデオプロセスの場合、両方のユーザーに、ビデオプロセス1から、場合によっては別のプロセス1からの混合進行状況が表示されます。

静的変数で開始されたサーバー側のビデオプロセス。

public static MediaHandler _mhandler = new MediaHandler();

進行状況の表示が経由でページに送信されます

[WebMethod]
public static string GetProgressStatus()
{
    return Math.Round(_mhandler.vinfo.ProcessingCompleted, 2).ToString();
}

数秒ごとにプログレスバーから送信されるプログレスリクエスト。

ここで私の質問は、一度に1つのインスタンスのみをターゲットにできるmediahandlerオブジェクトを設定する方法です。

たとえば、プログレスバー01はビデオプロセス01のステータスのみを表示します

プログレスバー02は、ビデオプロセス02のステータスのみを表示します

4

4 に答える 4

1

ASP.NET と静的に注意してください - 静的な whatchagot は、同じ appdomain 内のセッション (ユーザー) 間でグローバルです (タイプに応じていくつかの違いがあります)。

ユーザー情報をセッション ストレージに保持します。または、少しクレイジーなことに、セッション ID を使用して複数のセッションを処理する静的メディア ハンドラー オブジェクトを用意し、セッション ID を使用してその進行状況を照会します。これは少し臭いかもしれませんが、セッションごとに独自のエンコーディングを生成できるようにしたい場合を除いて、これが必要な場合があります。

この回答を参照してください(この件に関する多くの回答の1つ)。ただし、マイクロソフトのナレッジベースの記事は、あまりにも不明確です。

于 2012-07-17T12:18:08.963 に答える
1

これは非常に単純なアプローチです。

静的リストの使用を検討しましたか??

リスト内の各項目は、バックグラウンド プロセスを実行しているハンドラーのインスタンスになります。それぞれのハンドラーを識別する必要があります。最も簡単な方法は、Guidそれぞれに を使用することです。

これはサンプルの作業コードです:

出力

ここに画像の説明を入力

ご覧のとおり、各ウィンドウは新しいプロセスを起動し、各ウィンドウは個別に更新されます

ASPX

<head runat="server">
    <title></title>
    <script type="text/javascript" src="Scripts/jquery-1.7.2.min.js"></script>
    <script type="text/javascript" src="Scripts/jquery.timer.js"></script>
    <script type="text/javascript">
        var timer;
        var currentProcess;
        function getProgress() {
            $.ajax({
                url: 'LongTimeOperations.aspx/GetStatus',
                data: '{"processID": "' + currentProcess + '"}',
                contentType: 'application/json; charset=utf-8;',
                dataType: 'json',
                type: "POST",
                async: true,
                cache: false,
                success: function (msg) {
                    $("#res").append("<br/>" + msg.d);
                    var r = msg.d;
                    if (typeof (r) === 'undefined' || r === null) {
                        timer.stop();
                    }
                },
                error: function (hxr) {
                    alert(hxr.responseText);
                }
            });
        }
        $(function () {
            $("#start").click(function () {
                $.ajax({
                    url: 'LongTimeOperations.aspx/StartProcess',
                    data: '{}',
                    contentType: 'application/json; charset=utf-8;',
                    dataType: 'json',
                    type: "POST",
                    async: true,
                    cache: false,
                    success: function (msg) {
                        alert(msg.d);
                        currentProcess = msg.d;
                        timer = $.timer(getProgress, 2000, true);
                    },
                    error: function (hxr) {
                        alert(hxr.responseText);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <input type="button" id="start" value="Start Process" />
        <p>
            <div id="res"></div>
        </p>
    </div>
    </form>
</body>

コードビハインド

    public static List<CurrentProcess> Processes = new List<CurrentProcess>();

    [WebMethod]
    public static Guid StartProcess()
    {
        Mutex mutex = new Mutex();
        mutex.WaitOne();

        var star = Thread.CurrentThread.ManagedThreadId.ToString();
        var p = new CurrentProcess(Guid.NewGuid());
        Processes.Add(p);

        var o = Observable.Start(() =>
        {
            var cap = p;
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(2000);
                var cp = Processes.FirstOrDefault(x => x.ID == cap.ID);

                if (cp != null)
                    cp.Status = string.Format("Current Process ID: {0}, Iteration: {1}, Starting thread: {2}, Execution thread: {3}",
                        cp.ID.ToString(),
                        i.ToString(),
                        star,
                        Thread.CurrentThread.ManagedThreadId.ToString()
                        );
            }
            Processes.RemoveAll(x => x.ID == cap.ID);
        }, Scheduler.NewThread);

        mutex.ReleaseMutex();
        mutex.Close();

        return p.ID;
    }

    [WebMethod]
    public static string GetStatus(Guid processID)
    {
        var p = Processes.FirstOrDefault(x => x.ID == processID);

        if (p != null)
            return p.Status;

        return null;
    }
}

public class CurrentProcess
{
    public Guid ID { get; set; }

    public string Status { get; set; }

    public CurrentProcess (Guid id)
    {
        this.ID = id;
    }
}

使用するライブラリ

このサンプルでは、​​Rx を使用して新しいスレッドを作成しています。別の方法を使用するように変更できます。

于 2012-07-17T14:28:28.060 に答える
1

Guidエンコーディングの存続期間中に使用される新しいエンコーディング リクエストごとに生成することをお勧めします。MediaHandlerまた、静的ではなく、エンコード タスクごとに new() を 1 つ作成することをお 勧めします。GetProgressStatus()エンコードごとの進行状況を照会できるように、Guid のパラメーターが必要になりました。

インスタンスを追跡するには、永続性 (データベース、静的リスト、MSMQ など) が必要です。MediaHandlerまた、現在の処理エンコーディングが連続して行われている場合は、進行状況を追跡する必要があります。

于 2012-07-17T13:01:41.720 に答える
1

アイデアを共有していただきありがとうございますが、残念ながら、すべてのユーザー間でほぼ共有されている静的オブジェクトを使用する場合の同時実行の問題を解決するソリューションはありません。今、私は問題を解決するいくつかの調整を行いました。

単一の静的オブジェクトを使用する代わりに、ジェネリック リスト オブジェクトを使用して、すべての同時処理オブジェクトをリストに格納しました。ここにコードがあります。

public static List<MediaHandler> _lst = new List<MediaHandler>();

MediaHandler は、動画の処理を担当するクラス名です。

次の関数は、ビデオ処理の開始を担当します

public static string EncodeVideo(string Source, string Published)
{   
 MediaHandler _mhandler = new MediaHandler(); 
 ..............
 ..............
 _mhandler.vinfo.ProcessID = Guid.NewGuid().ToString(); 
// unique guid to attach with each process to identify proper object on progress bar and get info request
// add media handler object in concurrent static list
 _lst.Add(_mhandler);
 return _mhandler.vinfo.ProcessID; // retuned unique identifier
}

適切なビデオ処理オブジェクトの進行状況を送信するために、各プログレス バーのリクエスト プロセス ID を関数に送信する必要があります。

[WebMethod]
public static string GetProgressStatus(string ProcessID)
{
    string completed_process = "0";
    if (_lst.Count > 0)
    {
        int i = 0;
        for (i = 0; i <= _lst.Count - 1; i++)
        {
            if (_lst[i].vinfo.ProcessID == ProcessID)
            {
                completed_process = Math.Round(_lst[i].vinfo.ProcessingCompleted, 2).ToString();
            }
        }
    }

    return completed_process;
}

処理が 100% 完了したら、すべてのビデオ情報をオブジェクトに保存し、メディア ハンドラー オブジェクトを静的同時リストから削除します。

if (_lst[i].vinfo.ProcessingCompleted >= 100)
{
    // remove from list of corrent processes if processes reach this point
    // store all information of completed process and remove it from list of concurrent processes
    // e.g
    VideoInfo current_uploaded_video_info = _lst[i].vinfo;
     _lst.Remove(_lst[i]);
}

このようにして、無制限の数の同時プロセスと進行状況バーのリクエストが可能になりました。

于 2012-07-18T18:09:20.667 に答える