在.net core環(huán)境下虹軟人臉(證)識別多線程的探討

? ? ? ?虹軟開放人臉識別SDK以來放仗,成功把人臉識別技術(shù)拉下神臺抑党,幾乎所有開發(fā)者可以“0成本”使用到人臉(證)到其項目包警。但在官方論壇,QQ群底靠,微信群等平臺害晦,很多初學(xué)者對如何在多線程下使用產(chǎn)生疑惑,掉入坑中(尤其是沒有C++的基礎(chǔ)的C#開發(fā))暑中。今天壹瘟,分享兩種.net (core)下的多線程使用方式,貢大家探討鳄逾。大家有更好的方式稻轨,也可以積極留言交流。

? ? ? ?先分析問題來源雕凹,為什么C#的一般多線程調(diào)用方式容易產(chǎn)生錯誤殴俱,尤其是“嘗試寫保護(hù)內(nèi)存”的錯誤。原因是C#開發(fā)使用的虹軟的算法SDK均為C++版本(Windows/Linux)枚抵,C++作為線程不安全的程序粱挡,可以直接操作內(nèi)存。多個線程同時調(diào)用一個引擎俄精,就是同時對一段內(nèi)存操作,產(chǎn)生內(nèi)存錯誤榕堰,程序崩潰竖慧。

解決方案一:基于ThreadLocal?強制一個線程捆綁一個引擎。

? ? ? ?ThreadLocal的主要作用是讓各個線程維持自己的變量逆屡。ThreadLocal 是線程的局部變量圾旨, 是每一個線程所單獨持有的,其他線程不能對其進(jìn)行訪問魏蔗,?通常是類中的 private static 字段砍的。當(dāng)使用ThreadLocal維護(hù)變量的時候 為每一個使用該變量的線程提供一個獨立的變量副本,即每個線程內(nèi)部都會有一個該變量莺治,這樣同時多個線程訪問該變量并不會彼此相互影響廓鞠,因此他們使用的都是自己從內(nèi)存中拷貝過來的變量的副本, 這樣就不存在線程安全問題谣旁,也不會影響程序的執(zhí)行性能床佳。在虹軟人臉的具體應(yīng)用中,毫無疑問榄审,把初始化好的引擎指針(C#中的Intptr類型)賦值給線程的Threadlocal砌们,就可以開心的玩耍了。找個網(wǎng)上的code演示下:(本人基于ThreadLocal 的工程找不到了)

static void Main()

{

var local = new ThreadLocal<IntPtr>();

//修改TLS的線程

Thread th = new Thread(() =>

{

local.Value = intptr; //虹軟引擎指針

DoSomething();? ? ? ?//虹軟人臉對比具體流程

})

th.Start();

th.Join();

}

解決方案二:基于“引擎池”實現(xiàn)多線程與高并發(fā)。

相比于方案一浪感,我更喜歡“引擎池”昔头,應(yīng)為它更方便靈活,還更適合.net core Web Api這樣的后端框架影兽。廢話不說揭斧,代碼伺候:

1. 定義"引擎池"接口 (由于我方業(yè)務(wù)需要,初始化了3個不同的引擎池赢笨,相關(guān)的引擎參數(shù)不相同)

public interface IEnginePoor

? ? {

? ? ? ? public ConcurrentQueue<IntPtr> FaceEnginePoor { get; set; }

? ? ? ? public ConcurrentQueue<IntPtr> IDEnginePoor { get; set; }

? ? ? ? public ConcurrentQueue<IntPtr> AIEnginePoor { get; set; }

? ? ? ? public IntPtr GetEngine(ConcurrentQueue<IntPtr> queue);

? ? ? ? public void PutEngine(ConcurrentQueue<IntPtr> queue, IntPtr item);

? ? }

2. 實現(xiàn)相關(guān)接口 (Arcsoft_Face_3_0 為虹軟dll的C#封裝)

public class Arcsoft_Face_Action : Arcsoft_Face_3_0, IEnginePoor

? ? {

? ? ? ? public string AppID { get; }

? ? ? ? public string AppKey { get; }

? ? ? ? public int FaceEngineNums { get; set; }

? ? ? ? public int IDEngineNums { get; set; }

? ? ? ? public int AIEngineNums { get; set; }

? ? ? ? public ConcurrentQueue<IntPtr> FaceEnginePoor { get; set; }

? ? ? ? public ConcurrentQueue<IntPtr> IDEnginePoor { get; set; }

? ? ? ? public ConcurrentQueue<IntPtr> AIEnginePoor { get; set; }

private int InitEnginePool()

? ? ? ? {

? ? ? ? ? ? try

? ? ? ? ? ? {

? ? ? ? ? ? ? ? for (int index = 0; index < FaceEngineNums; index++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? IntPtr enginePtr = IntPtr.Zero;

? ? ? ? ? ? ? ? ? ? Arcsoft_Face_Action faceAction = new Arcsoft_Face_Action(AppID, AppKey);

? ? ? ? ? ? ? ? ? ? enginePtr = faceAction.InitASFEnginePtr(ParmsBestPractice.faceBaseMask);

? ? ? ? ? ? ? ? ? ? PutEngine(FaceEnginePoor, enginePtr);

? ? ? ? ? ? ? ? ? ? Console.WriteLine($"FaceEnginePoor add {enginePtr}");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? for (int index = 0; index < IDEngineNums; index++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? IntPtr enginePtr = IntPtr.Zero;

? ? ? ? ? ? ? ? ? ? Arcsoft_Face_Action faceAction = new Arcsoft_Face_Action(AppID, AppKey);

? ? ? ? ? ? ? ? ? ? enginePtr = faceAction.InitASFEnginePtr(ParmsBestPractice.faceBaseMask);

? ? ? ? ? ? ? ? ? ? PutEngine(IDEnginePoor, enginePtr);

? ? ? ? ? ? ? ? ? ? Console.WriteLine($"IDEnginePoor add {enginePtr}");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? for (int index = 0; index < AIEngineNums; index++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? IntPtr enginePtr = IntPtr.Zero;

? ? ? ? ? ? ? ? ? ? int aiMask = FaceEngineMask.ASF_AGE | FaceEngineMask.ASF_GENDER | FaceEngineMask.ASF_FACE3DANGLE | FaceEngineMask.ASF_LIVENESS;

? ? ? ? ? ? ? ? ? ? Arcsoft_Face_Action faceAction = new Arcsoft_Face_Action(AppID, AppKey);

? ? ? ? ? ? ? ? ? ? enginePtr = faceAction.InitASFEnginePtr(ParmsBestPractice.faceBaseMask | aiMask);

? ? ? ? ? ? ? ? ? ? PutEngine(AIEnginePoor, enginePtr);

? ? ? ? ? ? ? ? ? ? Console.WriteLine($"AIEnginePoor add {enginePtr}");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? return 0;

? ? ? ? ? ? }

? ? ? ? ? ? catch (Exception ex)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? throw new Exception($"InitEnginePool--> exception {ex}");

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? public IntPtr GetEngine(ConcurrentQueue<IntPtr> queue)

? ? ? ? {

? ? ? ? ? ? IntPtr item = IntPtr.Zero;

? ? ? ? ? ? if (queue.TryDequeue(out item))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return item;

? ? ? ? ? ? }

? ? ? ? ? ? else

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return IntPtr.Zero;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? public void PutEngine(ConcurrentQueue<IntPtr> queue, IntPtr item)

? ? ? ? {

? ? ? ? ? ? if (item != IntPtr.Zero)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? queue.Enqueue(item);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? public void Arcsoft_EnginePool(int faceEngineNums , int idEngineNums , int aiEngineNums)

? ? ? ? {

? ? ? ? ? ? FaceEnginePoor = new ConcurrentQueue<IntPtr>();

? ? ? ? ? ? IDEnginePoor = new ConcurrentQueue<IntPtr>();

? ? ? ? ? ? AIEnginePoor = new ConcurrentQueue<IntPtr>();

? ? ? ? ? ? try

? ? ? ? ? ? {

? ? ? ? ? ? ? ? FaceEngineNums = faceEngineNums;

? ? ? ? ? ? ? ? IDEngineNums = idEngineNums;

? ? ? ? ? ? ? ? AIEngineNums = aiEngineNums;

? ? ? ? ? ? ? ? int status = InitEnginePool();

? ? ? ? ? ? ? ? if (status != 0)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? throw new Exception("引擎池初始化失斘打颉!");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? catch (Exception ex)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? throw new Exception($"ArcSoft_EnginePool-->ArcSoft_EnginePool exception as: {ex}");

? ? ? ? ? ? }

? ? ? ? }

private int InitEnginePool()

? ? ? ? {

? ? ? ? ? ? try

? ? ? ? ? ? {

? ? ? ? ? ? ? ? for (int index = 0; index < FaceEngineNums; index++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? IntPtr enginePtr = IntPtr.Zero;

? ? ? ? ? ? ? ? ? ? Arcsoft_Face_Action faceAction = new Arcsoft_Face_Action(AppID, AppKey);

? ? ? ? ? ? ? ? ? ? enginePtr = faceAction.InitASFEnginePtr(ParmsBestPractice.faceBaseMask);

? ? ? ? ? ? ? ? ? ? PutEngine(FaceEnginePoor, enginePtr);

? ? ? ? ? ? ? ? ? ? Console.WriteLine($"FaceEnginePoor add {enginePtr}");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? for (int index = 0; index < IDEngineNums; index++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? IntPtr enginePtr = IntPtr.Zero;

? ? ? ? ? ? ? ? ? ? Arcsoft_Face_Action faceAction = new Arcsoft_Face_Action(AppID, AppKey);

? ? ? ? ? ? ? ? ? ? enginePtr = faceAction.InitASFEnginePtr(ParmsBestPractice.faceBaseMask);

? ? ? ? ? ? ? ? ? ? PutEngine(IDEnginePoor, enginePtr);

? ? ? ? ? ? ? ? ? ? Console.WriteLine($"IDEnginePoor add {enginePtr}");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? for (int index = 0; index < AIEngineNums; index++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? IntPtr enginePtr = IntPtr.Zero;

? ? ? ? ? ? ? ? ? ? int aiMask = FaceEngineMask.ASF_AGE | FaceEngineMask.ASF_GENDER | FaceEngineMask.ASF_FACE3DANGLE | FaceEngineMask.ASF_LIVENESS;

? ? ? ? ? ? ? ? ? ? Arcsoft_Face_Action faceAction = new Arcsoft_Face_Action(AppID, AppKey);

? ? ? ? ? ? ? ? ? ? enginePtr = faceAction.InitASFEnginePtr(ParmsBestPractice.faceBaseMask | aiMask);

? ? ? ? ? ? ? ? ? ? PutEngine(AIEnginePoor, enginePtr);

? ? ? ? ? ? ? ? ? ? Console.WriteLine($"AIEnginePoor add {enginePtr}");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? return 0;

? ? ? ? ? ? }

? ? ? ? ? ? catch (Exception ex)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? throw new Exception($"InitEnginePool--> exception {ex}");

? ? ? ? ? ? }

? ? ? ? }

}

3. 實現(xiàn)CustomServiceCollection 方便依賴注入

public static class CustomServiceCollection

? ? {

? ? ? ? public static IServiceCollection AddArcSoftFaceService(this IServiceCollection services, Arcsoft_Face_Action enginePool)

? ? ? ? {

? ? ? ? ? ? services.AddSingleton<IEnginePoor, Arcsoft_Face_Action>(x => enginePool);

? ? ? ? ? ? return services;

? ? ? ? }

? ? }

4. 在Startup里面添加“虹軟”Service茧妒。(同時推薦搭配Microsoft.AspNetCore.ConcurrencyLimiter中間件萧吠,限制并發(fā)量,以免內(nèi)存不足)

public void ConfigureServices(IServiceCollection services)

? ? ? ? {

? ? ? ? ? ? services.AddMvc();

? ? ? ? ? ? services.AddControllers();

? ? ? ? ? ? //用于傳入的請求進(jìn)行排隊處理,避免線程池的不足.

? ? ? ? ? ? services.AddQueuePolicy(options =>

? ? ? ? ? ? {

? ? ? ? ? ? ? ? //最大并發(fā)請求數(shù) (建議與引擎數(shù)保持一直桐筏,虹軟官方的說法是的最大引擎數(shù)不超過電腦的核數(shù)纸型,我反正是不信的,難道志強和奔騰一樣梅忌?內(nèi)存足夠大狰腌,我一般是和虛擬線程數(shù)一致,比如6核12線程牧氮,我就開12個引擎琼腔。)

? ? ? ? ? ? ? ? options.MaxConcurrentRequests = faceEngineNums;

? ? ? ? ? ? ? ? //請求隊列長度限制

? ? ? ? ? ? ? ? options.RequestQueueLimit = requestQueueLimit;

? ? ? ? ? ? });

? ? ? ? ? ? //添加虹軟“引擎池”服務(wù)

? ? ? ? ? ? Arcsoft_Face_Action enginePool = new Arcsoft_Face_Action(appID, faceKey);

? ? ? ? ? ? enginePool.Arcsoft_EnginePool(faceEngineNums, 0, 0);

? ? ? ? ? ? services.AddArcSoftFaceService(enginePool);

? ? ? ? }

5.??在Controller里面實際使用。

public class FaceController : ControllerBase

{

public FaceController(IConfiguration configuration, IEnginePoor process)

? ? ? ? {

? ? ? ? ? ? Configuration = configuration;

? ? ? ? ? ? FaceProcess = process;

? ? ? ? ? ? float.TryParse(Configuration.GetSection("AppSettings:FaceMixLevel").Value, out faceMix);

? ? ? ? ? ? int.TryParse(Configuration.GetSection("AppSettings:MaxProcessTime").Value, out maxProcessTime);

? ? ? ? }

[HttpPost]

? ? ? ? [Route("CompareTwoFaces")]

? ? ? ? [DisableRequestSizeLimit]

? ? ? ? public IActionResult CompareTwoFaces(IFormFile faceA, IFormFile faceB)

? ? ? ? {

? ? ? ? ? ? IntPtr engine = FaceProcess.GetEngine(FaceProcess.FaceEnginePoor);

? ? ? ? ? ? CancellationTokenSource tokenSource = new CancellationTokenSource();

? ? ? ? ? ? CustomResult faceResult = new CustomResult();

? ? ? ? ? ? Tuple<bool, IntPtr, string> faceAResult = new Tuple<bool, IntPtr, string>(false, IntPtr.Zero, null);

? ? ? ? ? ? Tuple<bool, IntPtr, string> faceBResult = new Tuple<bool, IntPtr, string>(false, IntPtr.Zero, null);

? ? ? ? ? ? //調(diào)用引擎池邏輯踱葛!

? ? ? ? ? ? var task = Task.Run(() =>

? ? ? ? ? ? {

? ? ? ? ? ? ? ? while (engine == IntPtr.Zero)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? Task.Delay(10);

? ? ? ? ? ? ? ? ? ? if (tokenSource.Token.IsCancellationRequested)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? throw new Exception("等待引擎超時丹莲!");

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? engine = FaceProcess.GetEngine(FaceProcess.FaceEnginePoor);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? using (var ms = new MemoryStream())

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? faceA.CopyTo(ms);

? ? ? ? ? ? ? ? ? ? faceAResult = Arcsoft_Face_Action.TryExtractSingleFaceFeature(ms, 10, engine);

? ? ? ? ? ? ? ? ? ? if (!faceAResult.Item1)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? faceResult.Success = false;

? ? ? ? ? ? ? ? ? ? ? ? faceResult.msg = faceAResult.Item3;

? ? ? ? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? using (var ms = new MemoryStream())

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? faceB.CopyTo(ms);

? ? ? ? ? ? ? ? ? ? faceBResult = Arcsoft_Face_Action.TryExtractSingleFaceFeature(ms, 10, engine);

? ? ? ? ? ? ? ? ? ? if (!faceBResult.Item1)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? faceResult.Success = false;

? ? ? ? ? ? ? ? ? ? ? ? faceResult.msg = faceBResult.Item3;

? ? ? ? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? float result = 0;

? ? ? ? ? ? ? ? int compareStatus = Arcsoft_Face_3_0.ASFFaceFeatureCompare(engine, faceAResult.Item2, faceBResult.Item2, ref result, ASF_CompareModel.ASF_LIFE_PHOTO);

? ? ? ? ? ? ? ? if (compareStatus == 0)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? faceResult.Success = true;

? ? ? ? ? ? ? ? ? ? faceResult.msg = $"相似度: {result} 接客引擎:{engine}";

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? faceResult.Success = false;

? ? ? ? ? ? ? ? ? ? faceResult.msg = $"compareStatus error code = {compareStatus} 接客引擎:{engine}";

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }, tokenSource.Token);

? ? ? ? ? ? //響應(yīng)時間控制

? ? ? ? ? ? try

? ? ? ? ? ? {

? ? ? ? ? ? ? ? int timeLast = maxProcessTime * 1000;

? ? ? ? ? ? ? ? while (timeLast > 0)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? Task.Delay(100).Wait();

? ? ? ? ? ? ? ? ? ? timeLast = timeLast - 100;

? ? ? ? ? ? ? ? ? ? if (task.IsCompletedSuccessfully)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? return Ok(JsonConvert.SerializeObject(faceResult));

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? tokenSource.Cancel();

? ? ? ? ? ? ? ? return Ok(JsonConvert.SerializeObject(faceResult));

? ? ? ? ? ? }

? ? ? ? ? ? catch (Exception ex)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? faceResult.Success = false;

? ? ? ? ? ? ? ? faceResult.msg = ex.Message;

? ? ? ? ? ? ? ? return Ok(JsonConvert.SerializeObject(faceResult));

? ? ? ? ? ? }

? ? ? ? ? ? finally

? ? ? ? ? ? {

? ? ? ? ? ? ? ? FaceProcess.PutEngine(FaceProcess.FaceEnginePoor, engine);

? ? ? ? ? ? ? ? Marshal.FreeHGlobal(faceAResult.Item2);

? ? ? ? ? ? ? ? Marshal.FreeHGlobal(faceBResult.Item2);

? ? ? ? ? ? ? ? tokenSource.Dispose();

? ? ? ? ? ? ? ? GC.Collect();

? ? ? ? ? ? }

? ? ? ? }

}

6.??結(jié)果演示:


后記:

? ? ? ?多線程一般是為應(yīng)對高并發(fā)的情形,本篇文章僅僅提供一種應(yīng)對虹軟人臉識別的多線程的簡單初級處理方式尸诽,但對于真正的互聯(lián)網(wǎng)級別的高并發(fā)甥材,肯定是力不從心的。筆者在其他高并發(fā)項目中性含,還是基于k8s的redis+Kafka的分布式微服務(wù)架構(gòu)處理洲赵,一個pod里面一個引擎(有點廢號)。當(dāng)然商蕴,Adp vNext也很香叠萍。對于私人開發(fā)者,每年100個注冊碼绪商,k8s的消耗可能太大俭令,本文的方式還是能節(jié)約一些注冊碼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末部宿,一起剝皮案震驚了整個濱河市抄腔,隨后出現(xiàn)的幾起案子瓢湃,更是在濱河造成了極大的恐慌,老刑警劉巖赫蛇,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绵患,死亡現(xiàn)場離奇詭異,居然都是意外死亡悟耘,警方通過查閱死者的電腦和手機落蝙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暂幼,“玉大人筏勒,你說我怎么就攤上這事⊥遥” “怎么了管行?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邪媳。 經(jīng)常有香客問我捐顷,道長,這世上最難降的妖魔是什么雨效? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任迅涮,我火速辦了婚禮,結(jié)果婚禮上徽龟,老公的妹妹穿的比我還像新娘叮姑。我一直安慰自己,他們只是感情好据悔,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布传透。 她就那樣靜靜地躺著,像睡著了一般屠尊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耕拷,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天讼昆,我揣著相機與錄音,去河邊找鬼骚烧。 笑死浸赫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赃绊。 我是一名探鬼主播既峡,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼碧查!你這毒婦竟也來了运敢?” 一聲冷哼從身側(cè)響起校仑,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎传惠,沒想到半個月后迄沫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡卦方,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年羊瘩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盼砍。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡尘吗,死狀恐怖浇坐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侧戴,我是刑警寧澤跌宛,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布疆拘,位于F島的核電站,受9級特大地震影響回右,放射性物質(zhì)發(fā)生泄漏翔烁。R本人自食惡果不足惜旨涝,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一白华、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厦取,春花似錦管搪、人聲如沸铡买。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纠亚。三九已至筋夏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間骗随,已是汗流浹背赴叹。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工乞巧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留涨椒,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓绽媒,卻偏偏與公主長得像蚕冬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子是辕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355