在WPF

时间:2015-06-23 16:22:15

标签: c# .net wpf wcf asynchronous

我一直在网上搜索此内容,并且无法找到真正有效的解决方案。情况如下:我有一个WPF应用程序,我想向用户呈现一个简单的登录表单。尝试使用MVVM,所以我在login命令后面有一个带有以下代码的LoginViewModel:

try
        {
            WithClient(servfact.GetServiceClient<IAccountService>(), proxy =>
            {
                principal = proxy.AuthenticateUser(Login, password);
            });
            Thread.CurrentPrincipal = principal;
        }
        catch(...) { ... }

&#34; WithClient&#34;是我的viewmodel基类中的一个简短方法,我用它来实例化和处理我的服务代理:

    protected void WithClient<T>(T proxy, Action<T> codeToExecute)
    {
        try { codeToExecute(proxy); }
        finally
        {
            IDisposable toDispose = (proxy as IDisposable);
            if(toDispose != null) { toDispose.Dispose(); }
        }
    }

现在,我的大多数服务都是Async,并且我有一个Asyncient的异步变体,这也很好用:

        protected async Task WithClientAsync<T>(T proxy, Func<T, Task> codeToExecute)
    {
        try { await codeToExecute(proxy); }
        finally
        {
            IDisposable toDispose = (proxy as IDisposable);
            if(toDispose != null) { toDispose.Dispose(); }
        }
    }

每当我也想异步登录时,麻烦就开始了。显然,我不希望UI在我登录时冻结(或者访问任何WCF服务)。这本身工作正常,但问题出在我设置CurrentPrincipal的代码段中。你们大多数人可能都很熟悉这个问题:它似乎设置得很好。然后在我的程序中,我想使用CurrentPrincipal(在客户端或者将用户登录到messageheader中的WCF服务),但它似乎被重置为标准的GenericPrincipal。当我将登录恢复为同步时,CurrentPrincipal就可以了。简而言之:如何在异步代码中设置主体,让它在以后持续存在,而不是恢复到标准主体?

1 个答案:

答案 0 :(得分:1)

嗯,好吧,一年没有回答。不用担心,因为我自己设法解决了这个问题:我只是在它周围包裹了一个单身人士:

// SOURCE: http://stackoverflow.com/questions/39302814/mediastream-capture-canvas-and-audio-simultaneously#39302994
var cStream,
    aStream,
    recorder,
    chunks = [],
    canvasEl = document.createElement('canvas');

canvasEl.width = 400;
canvasEl.height = 400;
document.body.appendChild(canvasEl);

/*
   create and run external video
*/
var videoEl = document.createElement('video');
videoEl.crossOrigin = 'anonymous';
videoEl.src = 'https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4';
videoEl.play();
videoEl.addEventListener('play', function(){
    var audioCtx = new AudioContext();
    var dest = audioCtx.createMediaStreamDestination();

    aStream = dest.stream;
    var sourceNode = audioCtx.createMediaElementSource(this);
    console.log('connected audio');
    sourceNode.connect(dest);

    // output to our headphones  
    sourceNode.connect(audioCtx.destination)

    var canvasCtx = canvasEl.getContext('2d');
    console.log('play video in canvas');
    draw(this, canvasCtx);

    startRecording();
    setTimeout(() => {
        stopRecording();
    }, 10000)      

}, false);


function exportStream(e) {
    console.log('exportStream', chunks.length);
    if (chunks.length) {
        var blob = new Blob(chunks),
            videoURL = URL.createObjectURL(blob),
            resultVideoEl = document.createElement('video');

        resultVideoEl.controls = true;
        resultVideoEl.src = videoURL;
        resultVideoEl.onend = function() {
            URL.revokeObjectURL(videoURL);
        }
        document.body.insertBefore(resultVideoEl, canvasEl);

    } else {
        document.body.insertBefore(
            document.createTextNode('no data saved'), canvasEl);
    }
}


function saveChunks(e) {
    console.log('save chunks', e.data.size);
    e.data.size && chunks.push(e.data);
}


function stopRecording() {
    console.log('STOP RECORDING');
    videoEl.pause();
    recorder.stop();
}


function startRecording() {
    console.log('START RECORDING');
    cStream = canvasEl.captureStream(30);
    cStream.addTrack(aStream.getAudioTracks()[0]);

    recorder = new MediaRecorder(cStream);
    recorder.start();

    // =============================================
    // THIS PART IS NOT FIRED WHEN RUN IN BACKGROUND
    // and final chunks is always an empty array. 
    // =============================================
    recorder.ondataavailable = saveChunks;
    recorder.onstop = exportStream;
}


function draw(v,ctx) {
    if(videoEl.paused || videoEl.ended) return false;

    // here I'm cropping the video frames and taking only 400 by 400
    // square shifted by 100, 100 vector
    ctx.drawImage(v, 100, 100, 400, 400, 0, 0, 400,400);
    setTimeout(draw,20,v,ctx);
}

所以我在登录后设置了它。我想问题是我在另一个线程中设置了主体,当我离开时它就丢失了?