C# 在特殊线程上运行进程并等待结果
我有一个简单的代码 var map=新的参考实体容量UOW; ... 这很好 但是现在,由于它的递归性,我需要在另一个具有较大堆栈大小的线程上运行它,并在继续之前等待它的结果 最简单的方法是什么? 我看不出有什么方法可以给任务指定一个特定的线程,或者告诉它创建一个具有大堆栈的线程 背景(如需要): 上面我已经使用了几个月的代码突然开始抛出堆栈溢出异常。我相信我刚刚达到了一个极限,因为它现在正在处理近140k个具有关系的实体,以决定它们在初始化新数据库时应该保存的顺序。 我不能改变递归部分——它位于我使用的外部第三方库中,我没有更新它的计划 我已经破解了测试代码,以证明它在大型堆栈线程上进行处理时确实有效。您可以将线程类与maxStackSize构造函数一起使用,但如果您想保持任务语义,则必须实现自定义TaskScheduler,如下所示:C# 在特殊线程上运行进程并等待结果,c#,multithreading,task-parallel-library,stack-overflow,C#,Multithreading,Task Parallel Library,Stack Overflow,我有一个简单的代码 var map=新的参考实体容量UOW; ... 这很好 但是现在,由于它的递归性,我需要在另一个具有较大堆栈大小的线程上运行它,并在继续之前等待它的结果 最简单的方法是什么? 我看不出有什么方法可以给任务指定一个特定的线程,或者告诉它创建一个具有大堆栈的线程 背景(如需要): 上面我已经使用了几个月的代码突然开始抛出堆栈溢出异常。我相信我刚刚达到了一个极限,因为它现在正在处理近140k个具有关系的实体,以决定它们在初始化新数据库时应该保存的顺序。 我不能改变递归部分——它位
public class BigStackTaskScheduler : TaskScheduler
{
private int _stackSize;
public BigStackTaskScheduler(int stackSize)
{
_stackSize = stackSize;
}
// we don't need to keep a tasks queue here
protected override IEnumerable<Task> GetScheduledTasks()
{
return new Task [] { };
}
protected override void QueueTask(Task task)
{
var thread = new Thread(ThreadWork, _stackSize);
thread.Start(task);
}
// we aren't going to inline the execution
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
QueueTask(task);
return false;
}
private void ThreadWork(object obj)
{
if (obj is Task task)
TryExecuteTask(task);
}
}
class Program
{
async static Task Test()
{
var taskFactory = new TaskFactory(
CancellationToken.None, TaskCreationOptions.DenyChildAttach,
TaskContinuationOptions.None, new BigStackTaskScheduler(0xffff * 2));
await taskFactory.StartNew(() => { Console.WriteLine("Task"); });
}
static void Main(string[] args)
{
Test().Wait();
}
}
对我来说,增加堆栈大小似乎是一种恶作剧,而且这种恶作剧在将来只会再次发生。你不能重构代码使其不是递归的吗?你可以手动创建一个新线程,或者使用Task.Factory.StartNew的TaskCreationOptions.LongRunning选项强制使用一个专用线程。我特别包括了背景文本,说重构递归是不可能的——不是我的代码!Longlung不行,它必须有一个巨大的堆栈。这段代码只需要一两秒钟的时间就可以运行,只是在试图处理这些实体时,它自己消失了。这段代码只用于将数据导入到新的数据库中。从那以后就再也不会有问题了。这些看起来很有希望,我明天第一件事就是要看一看,但我承认我对Tasks/wait/async不太熟悉。在Main中,我将有一个UOW-UOW实例,我希望将它传递给在这个bigstack线程上运行的方法,该方法将返回一个MAP-MAP实例,这样我就可以在Main的线程上处理它。我想我可以试着用Func而不是Action来重构你的上一段代码,这样它就变得通用了。@SimonHewitt,我修改了TaskCompletionSource示例,使其更通用。请演示Func.Super的可能用法!我的一行代码被一行代码替换:var map=ThreadWithCustomStackuowArg=>newreferencedentitypapaceuowarg,uow,1_0000_000.Result;
class Program
{
static Task<TOut> ThreadWithCustomStack<TIn, TOut>(Func<TIn, TOut> action, TIn arg, int stackSize)
{
var tcs = new TaskCompletionSource<TOut>();
var thread = new Thread(new ThreadStart(() =>
{
try
{
tcs.SetResult(action(arg));
}
catch (Exception e)
{
tcs.SetException(e);
}
}), stackSize);
thread.Start();
thread.Join();
return tcs.Task;
}
async static Task Test()
{
var result = await ThreadWithCustomStack(
arg => { Console.WriteLine("Task"); return arg.ToString(); },
2,
0xffff * 2);
}
static void Main(string[] args)
{
Test().Wait();
}
}