Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 使用TPL将“一次性”对象安全地传递到UI线程_C# 4.0_Task Parallel Library_Idisposable_Ui Thread - Fatal编程技术网

C# 4.0 使用TPL将“一次性”对象安全地传递到UI线程

C# 4.0 使用TPL将“一次性”对象安全地传递到UI线程,c#-4.0,task-parallel-library,idisposable,ui-thread,C# 4.0,Task Parallel Library,Idisposable,Ui Thread,我们最近采用了TPL作为运行一些繁重后台任务的工具包 这些任务通常会生成一个实现IDisposable的对象。这是因为它内部有一些操作系统句柄 我希望发生的是,后台线程生成的对象将始终得到正确处理,也就是在切换与应用程序关闭同时发生时 经过一番思考,我写了这样一篇文章: private void RunOnUiThread(Object data, Action<Object> action) { var t = Task.Factory.StartN

我们最近采用了TPL作为运行一些繁重后台任务的工具包

这些任务通常会生成一个实现
IDisposable
的对象。这是因为它内部有一些操作系统句柄

我希望发生的是,后台线程生成的对象将始终得到正确处理,也就是在切换与应用程序关闭同时发生时

经过一番思考,我写了这样一篇文章:

    private void RunOnUiThread(Object data, Action<Object> action)
    {
        var t = Task.Factory.StartNew(action, data, CancellationToken.None, TaskCreationOptions.None, _uiThreadScheduler);
        t.ContinueWith(delegate(Task task)
            {
                if (!task.IsCompleted)
                {
                    DisposableObject.DisposeObject(task.AsyncState);
                }
            });            
    }
private void RunOnUiThread(对象数据、操作)
{
var t=Task.Factory.StartNew(操作、数据、CancellationToken.None、TaskCreationOptions.None、\uUIThreadScheduler);
t、 继续(委托(任务)
{
如果(!task.IsCompleted)
{
DisposableObject.DisposeObject(task.AsyncState);
}
});            
}
后台
任务
调用
RunOnUiThread
将其结果传递给UI线程。任务
t
在UI线程上调度,并获得传入的
数据的所有权。我希望如果由于ui线程的消息泵关闭而导致
t
无法执行,则继续将运行,我可以看到任务失败,并自行处理该对象
DisposeObject()
是一个帮助程序,它在处理对象之前检查对象是否确实可标识且不为null

可悲的是,它不起作用。如果在创建后台任务
t
后关闭应用程序,则不会执行继续

我以前解决过这个问题。当时我正在使用线程池和WPF调度程序在UI线程上发布消息。虽然不太漂亮,但最终还是成功了。我希望TPL在这方面做得更好。如果我能以某种方式告诉TPL,如果它们实现IDisposable,它应该处理所有剩余的AsyncState对象,那就更好了


因此,代码主要是为了说明问题。我想了解任何允许我将一次性对象从后台任务安全地移交给UI线程的解决方案,最好是使用尽可能少的代码

看看RX库。这可以让您做您想做的事情。

看看RX库。这可以让您做您想做的事。

来自:

IsCompleted
当任务位于三个选项之一时,将返回true 最终状态:
RanToCompletion
Faulted
cancelled

换句话说,您的
DisposableObject.DisposeObject
永远不会被调用,因为在上述条件之一发生后,将始终计划继续。我相信你的意思是:

t.ContinueWith(t => DisposableObject.DisposeObject(task.AsyncState),
               TaskContinuationOptions.NotOnRanToCompletion)
(顺便说一句,您可以简单地捕获
数据
变量,而不是使用
异步状态
属性)

但是,我不会对您希望确保始终发生的事情使用延续。我相信
try finally
块在这里更合适:

private void RunOnUiThread2(Object data, Action<Object> action)
{
    var t = Task.Factory.StartNew(() => 
    {
        try
        {
            action(data);
        }
        finally
        {
            DisposableObject.DisposeObject(task.AsyncState); 
            //Or use a new *foreground* thread if the disposing is heavy
        }
    }, CancellationToken.None, TaskCreationOptions.None, _uiThreadScheduler);
}
private void RunOnUiThread2(对象数据、操作)
{
var t=Task.Factory.StartNew(()=>
{
尝试
{
行动(数据);
}
最后
{
DisposableObject.DisposeObject(task.AsyncState);
//如果处理量很大,也可以使用新的“前台”线程
}
},CancellationToken.None,TaskCreationOptions.None,\u uiThreadScheduler);
}
来自:

IsCompleted
当任务位于三个选项之一时,将返回true 最终状态:
RanToCompletion
Faulted
cancelled

换句话说,您的
DisposableObject.DisposeObject
永远不会被调用,因为在上述条件之一发生后,将始终计划继续。我相信你的意思是:

t.ContinueWith(t => DisposableObject.DisposeObject(task.AsyncState),
               TaskContinuationOptions.NotOnRanToCompletion)
(顺便说一句,您可以简单地捕获
数据
变量,而不是使用
异步状态
属性)

但是,我不会对您希望确保始终发生的事情使用延续。我相信
try finally
块在这里更合适:

private void RunOnUiThread2(Object data, Action<Object> action)
{
    var t = Task.Factory.StartNew(() => 
    {
        try
        {
            action(data);
        }
        finally
        {
            DisposableObject.DisposeObject(task.AsyncState); 
            //Or use a new *foreground* thread if the disposing is heavy
        }
    }, CancellationToken.None, TaskCreationOptions.None, _uiThreadScheduler);
}
private void RunOnUiThread2(对象数据、操作)
{
var t=Task.Factory.StartNew(()=>
{
尝试
{
行动(数据);
}
最后
{
DisposableObject.DisposeObject(task.AsyncState);
//如果处理量很大,也可以使用新的“前台”线程
}
},CancellationToken.None,TaskCreationOptions.None,\u uiThreadScheduler);
}

当进程关闭时,它的所有内核句柄都会自动关闭。您不必为此担心:


当进程关闭时,它的所有内核句柄都会自动关闭。您不必为此担心:


实际上我已经看过了。您知道其中的
IDisposable
对象有什么特殊处理吗?不知道,但是由于IObservable总是调用OnError或OnCompleted,因此您可以在那里处理它。我明白了。。。。问题是,这在制作人身上并不例外,据我所知,OnError就是为了这个。但我无论如何都会尝试的。。。除非有人提出更好的建议,否则也不要错过派对,但要面向未来的读者和@Chriseyre2000。事实上,有特殊处理。使用类似以下内容创建可观察序列:
Observable。使用(()=>new MyDisposable(),d=>action(d)。ToObservable())
一旦序列完成,将处理一次性对象。注意:您可能还希望使用
Observable.Defer
,并以类似的方式将序列传递到该序列中。另外,
ToObservable
位于
System.Reactive.Threading.Tasks
命名空间中。实际上我有