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、その問題をほぼ 1 日処理しようとしてきました。

ところで:それはMVC4プロジェクトでありC# 5.0、私はTDDそれをすべてしようとしています.

4

1 に答える 1

1

そこに電話してはいけませんTasksToExecute.Dispose();

于 2012-12-03T09:18:13.973 に答える