---
# System prepended metadata

title: LabDataManager.cs

---

# LabDataManager.cs


### 主要修改處
 * 34
 * 72
 * 95 - 104

```csharp=
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DataSync;
using UnityEngine;



namespace LabData
{
    public enum SaveType
    {
        Json,
        Csv
    }

    public sealed class LabDataManager : ILabDataManager
    {
        //private SaveType _saveType = SaveType.Json;
        [SerializeField] private bool _sendToServer = false;

        public bool IsClientRunning { get; private set; }
        private bool _isClientInit = false;
        private static DataSyncClient _client;
        private string _saveDataPath;
        private LabDataScope Scope { get; set; }
        private Func<string> _userId;
        private SimpleApplicationLifecycle _applicationLifecycle;
        private string labDataSavePath => LabTools.DataPath + "/TestData";
        // private readonly List<DataWriter> _dataWriters = new List<DataWriter>();
        private string _localSaveDataTimeLayout;
        private ConcurrentQueue<LabDataBase> _dataQueue;
        private Thread _writeThread;
        private Dictionary<Type, LabDataWriter> _dataWriterDic;
        public Action<LabDataBase> GetDataAction { get; set; }




        /// <summary>
        /// 数据采集,传入数据,频率,是否循环采集
        /// </summary>
        /// <param name="data"></param> 
        /// <param name="loop"></param>
        /// <param name="frequency"></param>
        [Obsolete("功能弃用，新的使用方法请查看Demo")]
        public void DataCollect(LabDataBase data, bool loop = true, int frequency = 200)
        {

        }

        /// <summary>
        /// 传入UserID初始化LabDataCollect
        /// </summary>
        /// <param name="userId"></param>
        public void LabDataCollectInit(Func<string> userId)
        {

            if (_isClientInit)
            {
                return;
            }

            #region 初始化本地存储
            _localSaveDataTimeLayout = LabTools.GetConfig<LabDataConfig>().LocalSaveDataTimeLayout;
            _userId = userId;
            _saveDataPath = LabTools.DataPath + "/Output";
            LabTools.CreatSaveDataFolder(_saveDataPath);
            var userStr = _userId.Invoke().PadLeft(2, '0');
            _saveDataPath = string.Join("_", _saveDataPath + "/" + DateTime.Now.ToString(_localSaveDataTimeLayout), userStr);
            _saveDataPath = LabTools.CreatSaveDataFolder(_saveDataPath);
            #endregion

            #region 初始化上传服务

            var options = new DataSyncClientOptions()
            {
                EndpointAddress = "http://localhost:4000/api/data",
                ProjectId = LabTools.GetConfig<LabDataConfig>().ProjectId,
                LogFilePath = labDataSavePath + "/ log.txt"
            };

            //Docker
            options.EndpointAddress = "http://localhost/api/data";

            //server
            _sendToServer = LabTools.GetConfig<LabDataConfig>().SendToServer;
            options.EndpointAddress = LabTools.GetConfig<LabDataConfig>().ServerPath;

            string testStorePath = Path.Combine(LabTools.DataPath, "TestStore");
            if (!Directory.Exists(testStorePath))
            {
                Directory.CreateDirectory(testStorePath);
            }
            _applicationLifecycle = new SimpleApplicationLifecycle();


            _client = new DataSyncClient(new UnityApplicationFolderProvider(testStorePath),
                _applicationLifecycle, options, _userId);

            _client.Init();

            _isClientInit = true;

            StartUpload();

            #endregion

            Application.wantsToQuit += () => !IsClientRunning;
            _dataWriterDic = new Dictionary<Type, LabDataWriter>();
            _dataQueue = new ConcurrentQueue<LabDataBase>();
            _writeThread = new Thread(Queue2Send);
            _writeThread.Start();
        }


        async void ILabDataManager.LabDataDispose()
        {
            await Task.Run(() =>
            {
                while(_dataQueue.Count > 0)
                {
                    Debug.Log(( $"Remain {0} Data to be stored", _dataQueue.Count));
                    Thread.Sleep(100);                   
                }
            });
            foreach (var item in _dataWriterDic)
            {
                item.Value.WriterDispose();
            }
            GetDataAction = null;
            Debug.LogError("LabDataDispose");
            StopUpload();
            _isClientInit = false;
            // _dataWriters?.ForEach(p => p.Dispose());
        }

        /// <summary>
        /// 传输数据
        /// </summary>
        public void SendData(LabDataBase data)
        {
            _dataQueue.Enqueue(data);
            GetDataAction?.Invoke(data);
        }


        private void Queue2Send()
        {
            while (IsClientRunning)
            {
                var dataList = new List<LabDataBase>();
                while (_dataQueue.TryDequeue(out var resultData))
                {
                    dataList.Add(resultData);
                }
                foreach (var d in dataList)
                {
                    DoOnce(d);
                }
            }
        }
        private void DoOnce(LabDataBase data)
        {
            if (!_isClientInit)
            {
                Debug.LogError("LabData未初始化");
                return;
            }

            DataWriterFunc(data);

            if (_sendToServer)
            {
                Scope.Send(data);
            }

        }

        private void DataWriterFunc(LabDataBase data)
        {
            var datatype = data.GetType();
            if (!_dataWriterDic.ContainsKey(datatype))
            {
                string dataPath = string.Join("_", _saveDataPath + "/", _userId.Invoke().PadLeft(2, '0'), data.GetType().Name + ".json");
                LabTools.CreatData(dataPath);
                _dataWriterDic.Add(datatype, new LabDataWriter(dataPath));
            }

            _dataWriterDic[datatype].WriteData(data);
        }

        private void StartUpload()
        {
            if (IsClientRunning)
            {
                return;
            }
            Debug.Log("开始");
            _applicationLifecycle.OnStarted(EventArgs.Empty);
            Scope = _client.CreateNewScope();
            Scope.StartScope();
            IsClientRunning = true;
        }

        private void StopUpload()
        {
            if (!IsClientRunning)
            {
                return;
            }
            Debug.Log("停止");
            Scope.StopScope();
            Scope.Dispose();

            _applicationLifecycle.OnStopping(ApplicationStoppingEventArgs.Empty);
            IsClientRunning = false;
        }

    }

    public class LabDataWriter
    {
        private readonly FileStream _fs;
        private readonly StreamWriter _sw;
        public LabDataWriter(string path)
        {
            _fs = new FileStream(path, FileMode.Append, FileAccess.Write);
            _sw = new StreamWriter(_fs);

        }
        public void WriteData(LabDataBase data)
        {
            _sw.WriteLine(data.ToJson());
        }

        public void WriterDispose()
        {
            _sw.Flush();
            _fs.Close();
        }
    }
}





```