0

我有这个基类结构:基础:

public abstract class BackgroundTask
{
    protected readonly Logger Logger = LogManager.GetCurrentClassLogger();

    protected virtual void Initialize()
    {
        // initialize database access
    }

    public void Run()
    {
        Initialize();
        try
        {
            Execute();
            // insert to database or whatever
        }
        catch (Exception ex)
        {
            Logger.ErrorException(string.Format("Error proccesing task: {0}\r\n", ToString()), ex);
            Exceptions.Add(ex);
        }
        finally
        {
            TaskExecuter.Discard();
        }
    }

    protected abstract void Execute();
    public abstract override string ToString();
    public IList<Exception> Exceptions = new List<Exception>();
}

任务执行者:

public static class TaskExecuter
{
    private static readonly ThreadLocal<IList<BackgroundTask>> TasksToExecute
        = new ThreadLocal<IList<BackgroundTask>>(() => new List<BackgroundTask>());

    public static void ExecuteLater(BackgroundTask task)
    {
        TasksToExecute.Value.Add(task);
    }

    public static void StartExecuting()
    {
        foreach (var backgroundTask in TasksToExecute.Value)
        {
            Task.Factory.StartNew(backgroundTask.Run);
        }
    }

    public static void Discard()
    {
        TasksToExecute.Value.Clear();
        TasksToExecute.Dispose();
    }
}

文件任务:

public class FileTask : BackgroundTask
{
    protected static string BaseFolder = @"C:\ASCII\";
    private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
    private readonly string _folder;

    private IHistoryRepository _historyRepository;

    public string Folder
    {
        get { return _folder; }
    }

    public FileTask(string folder)
    {
        _folder = string.Format("{0}{1}", BaseFolder, folder);
    }

    protected override void Initialize()
    {
        _historyRepository = new HistoryRepository();
    }

    protected override void Execute()
    {
        // todo: Get institute that are active,
        var institute = MockInstitute(); // todo: uncomment _historyRepository.FindInstituteByFolderName(Folder);

        // todo: Update institute, lastupdate - [date] | [files amount] | [phonenumbers amount]
        if (institute == null)
        {
            Logger.Warn("Not found data", Folder);
            return;
        }

        // todo: read file get encoding | type and parse it
        Task.Factory.StartNew(ReadFile);
    }

    private void ReadFile()
    {
        var list = GetFilesByFolder();
        StreamReader sr = null;
        try
        {
            Lock.EnterReadLock();
            foreach (var fi in list)
            {
                var fileName = fi.FullName;
                Logger.Info("Line: {0}:=> Content: {1}", fileName, Thread.CurrentThread.ManagedThreadId);
                sr = new StreamReader(fileName, DetectEncoding(fileName));
                string currentLine;
                while ((currentLine = sr.ReadLine()).ReturnSuccess())
                {
                    if (string.IsNullOrEmpty(currentLine)) continue;
                    Logger.Info("Line: {0}:=> Content: {1}", fileName, currentLine);
                }
            }
            Lock.ExitReadLock();
        }
        finally
        {
            if (sr != null) sr.Dispose();
            Logger.Info("Finished working" + Folder);
        }
    }

    protected IEnumerable<FileInfo> GetFilesByFolder()
    {
        return Directory.GetFiles(Folder).Select(fileName => new FileInfo(fileName));
    }

    protected Encoding DetectEncoding(string file)
    {
        using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
        {
            var cdet = new Ude.CharsetDetector();
            cdet.Feed(fs);
            cdet.DataEnd();
            return cdet.With(x => x.Charset)
                       .Return(x => Encoding.GetEncoding(cdet.Charset),
                                    Encoding.GetEncoding("windows-1255"));
        }
    }

    private Institute MockInstitute()
    {
        return new Institute
        {
            FromFolderLocation = string.Format("{0}{1}", BaseFolder, Folder)
        };
    }

    public override string ToString()
    {
        return string.Format("Folder: {0}", Folder);
    }
}

当不读取文件一切正常时,会填充日志并且每件事都运行顺利,但是当我附加该Task.Factory.StartNew(ReadFile);方法时,我有一个异常。

例外:

Cannot access a disposed object.
Object name: 'The ThreadLocal object has been disposed.'.

我该如何解决这个问题?我可能需要改变LocalThread逻辑,或者什么 - 我一直试图处理这个问题,差不多一天了。

顺便说一句:这是一个MVC4项目,C# 5.0我正在TDD全力以赴。

4

1 回答 1

1

你不应该在TasksToExecute.Dispose(); 那里打电话。

于 2012-12-03T09:18:13.973 回答